Skip to content

Instantly share code, notes, and snippets.

@scottcagno
Created August 18, 2022 20:28
Show Gist options
  • Select an option

  • Save scottcagno/8fa8bd877366e009b16c183ee9d8346d to your computer and use it in GitHub Desktop.

Select an option

Save scottcagno/8fa8bd877366e009b16c183ee9d8346d to your computer and use it in GitHub Desktop.
bitwise operations
package main
import (
"fmt"
"strconv"
)
func main() {
fmt.Println()
var f BitField
fmt.Printf("%.32b (hex=0x%.8x)\n", f, f)
f.Set(127, 0)
fmt.Printf("%.32b (hex=0x%.8x)\n", f, f)
f.Set(63, 1)
fmt.Printf("%.32b (hex=0x%.8x)\n", f, f)
f.Set(255, 2)
fmt.Printf("%.32b (hex=0x%.8x)\n", f, f)
f.Set(13, 3)
fmt.Printf("%.32b (hex=0x%.8x)\n", f, f)
fmt.Println(f.Get(0), f.Get(1),f.Get(2), f.Get(3))
// Say you want to set the second bit in x to a 1
x := StoB("11100101")
// You make a number with that bit on...
y := StoB("00000010")
// And you do an OR operation...
z := BitOR(x, y)
PrintBits(x, y, z)
x = StoB("00000010")
fmt.Printf("%.8b << %d (produces %.8b) (left)\n", x, 1, LeftShift(x, 1))
x = StoB("00000010")
fmt.Printf("%.8b << %d (produces %.8b) (left)\n", x, 2, LeftShift(x, 2))
x = StoB("00001011")
fmt.Printf("%.8b >> %d (produces %.8b) (right)\n", x, 1, RightShift(x, 1))
// x = ^15
x1 := BitNOT(StoB("00001111"))
PrintBits(x1) // should be 11110000, aka 240
// x = 3 & 2
x2 := BitAND(StoB("00000011"), StoB("00000010"))
PrintBits(x2) // should be 00000010, aka 2
// x = 2 | 8
x3 := BitOR(StoB("00000010"), StoB("00001000"))
PrintBits(x3) // should be 00001010, aka 10
// x = 5 ^ 3
x4 := BitXOR(StoB("00000101"), StoB("00000011"))
PrintBits(x4) // should be 00000110, aka 6
}
// BitField is a way to use a single larger datatype to store many smaller values.
type BitField uint32
func (bf *BitField) Set(v uint8, pos int) {
*bf |= BitField(v) << (pos << 3)
}
func (bf BitField) Get(pos int) uint8 {
return uint8(bf >> BitField(pos<<3))
}
// StoB takes a binary string representation and converts it into an uint8.
func StoB(s string) uint8 {
b, err := strconv.ParseUint(s, 2, 8)
if err != nil {
panic(err)
}
return uint8(b)
}
// BitNOT is a binary operation that takes two equal-length binary representations and
// performs the logical NOT operation on each pair of the corresponding bits. NOT is a
// unary operation that performs logical negation on each bit, forming the ones' complement
// of the given binary value. Bits that are 0 become 1, and those that are 1 become 0.
func BitNOT(x uint8) uint8 {
return ^x
}
// BitAND is a binary operation that takes two equal-length binary representations and
// performs the logical AND operation on each pair of the corresponding bits. The result
// in each position is 1 if both bits are 1, otherwise the result is 0.
func BitAND(x, y uint8) uint8 {
return x & y
}
// BitOR is a binary operation that takes two equal-length binary representations
// and performs the logical inclusive OR operation on each pair of corresponding bits.
// The result in each position is 0 if both bits are 0, otherwise the result is 1.
func BitOR(x, y uint8) uint8 {
return x | y
}
// BitXOR is a binary operation that takes two equal-length binary representations and
// performs the logical exclusive OR operation (aka XOR) on each pair of corresponding bits.
// The result in each position is 1 if only one of the bits is 1, but will be 0 if both are
// 0 or both are 1. IE: 1 if the two bits are different, and 0 if they are the same.
func BitXOR(x, y uint8) uint8 {
return x ^ y
}
// LeftShift is a binary operation that moves each bit in the number to the left by the
// number of bits specified with `by`. When shifting left, the most-significant bit (MSB)
// is lost, and a 0 bit is inserted on the other end. IE: 0010 << 1 produces 0100. It is
// worth noting that a single left shift multiplies a binary number by 2.
func LeftShift(x, by uint8) uint8 {
return x << by
}
// RightShift is a binary operation that moves each bit in the number to the right by the
// number of bits specified with `by`. When shifting right, the least-significant bit (LSB)
// is lost, and a 0 bit is inserted on the other end. IE: 1011 >> 1 produces 0101.
func RightShift(x, by uint8) uint8 {
return x >> by
}
// PrintBits takes an uint8 and prints it out the binary value.
func PrintBits(bits ...uint8) {
for _, b := range bits {
fmt.Printf("%.8b (decimal %.3d, hex=0x%0.2x)\n", b, b, b)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment