Math 某些运营商之间的差异”|&引用&引用^&引用&引用&&引用&引用&^&引用;。戈兰尼

Math 某些运营商之间的差异”|&引用&引用^&引用&引用&&引用&引用&^&引用;。戈兰尼,math,go,operators,bitwise-operators,Math,Go,Operators,Bitwise Operators,最近我阅读了golang规范,遇到了一些有趣的操作员: & bitwise AND integers | bitwise OR integers ^ bitwise XOR integers &^ bit clear (AND NOT) integers 我尝试过使用它,但我唯一了解的是“|”加整数和“+”运算符还可以处理浮点数、字符串等 它们在实践中的用途是什么?有人能解释一下上面

最近我阅读了golang规范,遇到了一些有趣的操作员:

&    bitwise AND            integers
|    bitwise OR             integers
^    bitwise XOR            integers
&^   bit clear (AND NOT)    integers
我尝试过使用它,但我唯一了解的是“|”加整数和“+”运算符还可以处理浮点数、字符串等


它们在实践中的用途是什么?有人能解释一下上面这4个运算符吗?

当您必须处理字节级或位级数据时,按位运算符起作用

在这里,我列出了一些使用位操作和代码示例的示例(没有特定顺序):


1.它们很常见,是密码学和散列函数(例如)中许多算法的一部分

2.如果您想“节省”空间,并且将多个“bool”变量打包成一个
int
变量,则通常会使用它们。例如,您为每个bool变量分配一位。必须使用位运算符才能单独更改/读取位

例如,将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.另一个领域是压缩数据,您希望最大限度地利用
字节
,并使用其所有位存储/检索某些信息(位是计算和数字通信中的基本信息单位)

4.类似于压缩,但不完全相同:比特流。它还用于通过不发送完整字节而是发送具有任意位长度的字段来节省数据流中的空间

我已经编写并发布了一个高度优化的位级读写器包,在这里开源:。您将在其源代码中看到各种位操作的广泛使用

5.另一个实际用途:测试(整数)数的某些属性。知道整数的二进制表示()在二进制表示中有数字的某些特征。例如,如果最低位为0,则整数(在2的补码中)为偶数(可除以2):

func isEven(i int) bool {
    return i&0x01 == 0
}
通过测试整数的位,你还可以判断它是否是2的幂。例如,如果一个正数只包含一个
1
位,则它是2的幂(例如
2=0x02=00000010b
16=0x10=00010000
,但例如
17=0x11=0000001
不是2的幂)

6.许多编码/解码过程也使用位操作。最简单的是,它使用可变长度编码将unicode代码点(
rune
in Go)表示为字节序列。
可变长度编码的一个简单变体是,如果解码一个数字需要更多字节,则使用字节的最高位(如果0索引,则为第8位或第7位)来发出信号,剩余的7位始终是“有用”数据。您可以测试最高位并“分离”7个有用位,如下所示:

b := readOneByte()
usefulBits := b & 0x7f
hasMoreBytes := b & 0x80 != 0
使用这种可变长度编码的好处是,即使使用内存中8字节的
uint64
type-in-Go,也可以使用更少的字节来表示较小的数字(范围
0..127
中的数字只需要1字节!)。如果要存储或传输的样本有许多小值,仅此一项就可以将数据压缩到1/8=12.5%。缺点是大数字(即使在最高字节中也有位)将使用超过8个字节。它是否值得取决于样本的启发性

X.列表还在继续


在Go(以及许多其他编程语言)中,您是否可以不知道/不使用位运算符?答案是肯定的。但是如果你了解他们,有时他们可以让你的生活更轻松,你的程序更高效


如果你想了解更多关于这个主题的信息,请阅读维基百科的文章:和谷歌的术语“按位运算符教程”,这里有很多很好的文章。

要了解他们在技术上做了什么,请查看本文中的评论

package main

import "fmt"

func main() {
    // Use bitwise OR | to get the bits that are in 1 OR 2
    // 1     = 00000001
    // 2     = 00000010
    // 1 | 2 = 00000011 = 3
    fmt.Println(1 | 2)

    // Use bitwise OR | to get the bits that are in 1 OR 5
    // 1     = 00000001
    // 5     = 00000101
    // 1 | 5 = 00000101 = 5
    fmt.Println(1 | 5)

    // Use bitwise XOR ^ to get the bits that are in 3 OR 6 BUT NOT BOTH
    // 3     = 00000011
    // 6     = 00000110
    // 3 ^ 6 = 00000101 = 5
    fmt.Println(3 ^ 6)

    // Use bitwise AND & to get the bits that are in 3 AND 6
    // 3     = 00000011
    // 6     = 00000110
    // 3 & 6 = 00000010 = 2
    fmt.Println(3 & 6)  

    // Use bit clear AND NOT &^ to get the bits that are in 3 AND NOT 6 (order matters)
    // 3      = 00000011
    // 6      = 00000110
    // 3 &^ 6 = 00000001 = 1
    fmt.Println(3 &^ 6)
}

请注意,我给出了两个
|
的示例,以表明它并不像
1+5
那样是真正的加法


至于实际用途,我相信其他一些人可能会给出更多的例子,但一个常见的用途是为权限系统之类的东西创建标志位掩码。

读一本像Petzold的《代码》这样的书,了解二进制表示法和计算基础。谢谢!回答得真不错。你能推荐这本书吗?它为像我这样的新手解释了一些“低级”编程的基础知识?(没有深入到太多的技术和数学术语)@TimurFayzrakhmanov只要谷歌一下(术语“比特运算符教程”),互联网上有很多很好的教程。大多数是特定于语言的,但它们或多或少适用于所有编程语言。这里有一个很好的例子,可以在1分钟的谷歌搜索中找到:。同时阅读维基百科的文章:嗯。。。如果数字为偶数,则isOdd()函数实际上返回true。isOdd应检查==1@RayfenWindspear你说得对。我把奇数和偶数这两个词弄混了。更正了。这应该是公认的答案!