How would you set and clear a single bit in Go?

20,809

Solution 1

Here's a function to set a bit. First, shift the number 1 the specified number of spaces in the integer (so it becomes 0010, 0100, etc). Then OR it with the original input. This leaves the other bits unaffected but will always set the target bit to 1.

// Sets the bit at pos in the integer n.
func setBit(n int, pos uint) int {
    n |= (1 << pos)
    return n
}

Here's a function to clear a bit. First shift the number 1 the specified number of spaces in the integer (so it becomes 0010, 0100, etc). Then flip every bit in the mask with the ^ operator (so 0010 becomes 1101). Then use a bitwise AND, which doesn't touch the numbers AND'ed with 1, but which will unset the value in the mask which is set to 0.

// Clears the bit at pos in n.
func clearBit(n int, pos uint) int {
    mask := ^(1 << pos)
    n &= mask
    return n
}

Finally here's a function to check whether a bit is set. Shift the number 1 the specified number of spaces (so it becomes 0010, 0100, etc) and then AND it with the target number. If the resulting number is greater than 0 (it'll be 1, 2, 4, 8, etc) then the bit is set.

func hasBit(n int, pos uint) bool {
    val := n & (1 << pos)
    return (val > 0)
}

Solution 2

There is also a compact notation to clear a bit. The operator for that is &^ and called "and not".

Using this operator the clearBit function can be written like this:

// Clears the bit at pos in n.
func clearBit(n int, pos uint) int {
    n &^= (1 << pos)
    return n
}

Or like this:

// Clears the bit at pos in n.
func clearBit(n int, pos uint) int {
    return n &^ (1 << pos)
}
Share:
20,809

Related videos on Youtube

Kevin Burke
Author by

Kevin Burke

I build reliable software and design great experiences. I'm available for hire: https://burke.services

Updated on July 23, 2022

Comments

  • Kevin Burke
    Kevin Burke almost 2 years

    In Golang, how do you set and clear individual bits of an integer? For example, functions that behave like this:

     clearBit(129, 7) // returns 1
     setBit(1, 7)     // returns 129
    
  • twotwotwo
    twotwotwo about 10 years
    Note it might be simpler to just write x &= ^(1<<7) or x |= 1<<7 (or x ^= 1<<7 to toggle, or (x & 1<<7 == 0) to see if a bit is set). That's widely understood enough not to need a comment, but if you feel like you should explain (e.g., your team doesn't come from a bit-twiddling world), just comment about your intention on first use of each idiom. Also, folks often define constants representing bits or bit combos so they don't have to write out 1<<n and remember the right n each time, and iota can help make those constant declarations concise.
  • Kevin Burke
    Kevin Burke about 10 years
    Agreed, I just extracted the variables to help clarity/readability. It is possible the compiler is making these optimizations as well.
  • Jonguo
    Jonguo almost 3 years
    func hasBit(n int, pos uint) bool { val := n & (1 << pos) return !(val == 0) } hasBit should like this, when n = -1<<63 and pos == 63, val is <0 but the leading bit is 1