最近,我阅读了golang规范,并遇到了一些有趣的运算符:
& bitwise AND integers | bitwise OR integers ^ bitwise XOR integers &^ bit clear (AND NOT) integers
我尝试过使用它,但是我唯一了解的是“ |” 添加整数,“ +”运算符还可用于浮点数,字符串等。
它们在实践中的作用是什么?有人可以对上面这4个运算符给出一些解释吗?
当您必须处理 字节或位级数据 时,按位运算符会起作用。
在这里,我列出了一些使用位操作和代码示例的示例(无特定顺序):
1. 它们是 密码术 和 哈希函数 (例如MD5)中许多算法的通用和组成部分。
2. 如果您想“节省”空间并且 将多个“布尔”变量打包 到一个 变量中int,例如,您为每个布尔变量分配一个位,则通常也使用它们。您必须使用按位运算符才能单独更改/读取位。
int
例如,将8位/布尔打包成一个int:
flags := 0x00 // All flags are 0 flags |= 0x02 // Turn the 2nd bit to 1 (leaving rest unchanged) flags |= 0xff // Turn 8 bits (0..7) to 1 flags &= 0xfe // Set the lowest bit to 0 (leaving rest unchanged) istrue := flags&0x04 != 0 // Test if 3rd bit is 1
3. 另一个领域是 压缩数据 ,您希望充分利用这些 数据byte并使用其所有位来存储/获取一些信息(位是计算和数字通信中信息的基本单位)。
byte
4. 与压缩相似,但不完全相同: bitstreams 。它也通过不发送完整的字节而是发送具有任意位长的字段来节省数据流中的空间。
我已经编写并发布了高度优化的位级Reader和Writer程序包,在此处开源: **github.com/icza/bitio** 。您将在其源代码中看到各种位操作的广泛使用。
5. 另一实际用法: 测试(整数)数字的某些属性 。知道整数的二进制表示形式(二进制补码),二进制的数字形式具有某些特征。例如,如果最低位是0,则整数(以2的补码表示)是 偶数 (可以除以2):
func isEven(i int) bool { return i&0x01 == 0 }
通过测试整数的位,您还可以知道它是否是2的幂。例如,如果一个正数仅包含一位1,则它是2的幂(例如2 = 0x02 = 00000010b,16 = 0x10 = 00010000但17 = 0x11 = 00010001不是2的幂)。
1
2 = 0x02 = 00000010b
16 = 0x10 = 00010000
17 = 0x11 = 00010001
6. 许多编码/解码过程 也使用位操作。最简单的是UTF-8编码,它使用可变长度编码将unicode码点(runeGo中)表示为字节序列。 变长编码的一个简单变体是使用一个字节的最高位(如果索引为0,则使用8或7)来表示是否需要更多字节来解码一个数字,其余7位始终是“有用的”。 ”数据。您可以测试最高位并“分离” 7个有用的位,如下所示:
rune
b := readOneByte() usefulBits := b & 0x7f hasMoreBytes := b & 0x80 != 0
使用这种可变长度编码的好处是,即使您uint64在Go中使用的类型(在内存中为8个字节),仍可以使用较少的字节来表示较小的数字(范围内的数字0..127仅需要1个字节!)。如果要存储或传输的样本具有许多较小的值,则仅此一项就可以将数据压缩为1/8 = 12.5%。不利的一面是,大数字(即使在最高字节中也有位)将使用8个以上的字节。是否值得取决于样本的试探法。
uint64
0..127
X. 清单继续…
您可以在不知道/不使用Go(以及许多其他编程语言)的按位运算符的情况下生活吗?答案是肯定的。但是,如果您了解它们,有时它们可以使您的生活更轻松,程序更高效。
如果您想了解更多有关该主题的信息,请阅读Wikipedia文章:按位运算,然后使用Google术语“按位运算符教程”,那里有很多不错的文章。