Python提供了下列位操作符,它们分别对二进制整数类型int值的每一位进行逻辑结合、逻辑分离、排他分离、位反转、左移位和右移位。
&
|
^
~
<<
>>
在本节中,我们首先解释如下。
- 交叉点 (AND) :
&
- 分歧点 (OR) :
|
- 排他性-OR操作 (XOR) :
^
接下来,我们将讨论以下内容。
- 对负整数的位操作
- 位数翻转 ( NOT) :
~
- 位移 :
<<
,>>
关于如何用二进制、八进制和十六进制写整数,以及如何使用以下函数转换二进制、八进制和十六进制数字和字符串的更多信息,请参见以下文章。
bin()
oct()
hex()
format()
另外,对于布尔值(真、假)的逻辑操作(布尔操作),而不是位操作,请参考以下文章。使用and,or而不是&,|。
交叉点 (AND) : &经营者
这是一个使用&操作符进行逻辑和的例子,结果由bin()转换为二进制符号的字符串。
x = 9 # 0b1001 y = 10 # 0b1010 print(x & y) print(bin(x & y)) # 8 # 0b1000
分歧点 (OR) : |经营者
一个使用|运算符的逻辑乘积(OR)的例子,其结果通过bin()转换为二进制符号的字符串,并一起输出。
print(x | y) print(bin(x | y)) # 11 # 0b1011
排他性-OR操作 (XOR) : ^经营者
使用^运算符的逻辑乘积(XOR)的例子,结合使用bin()转换为二进制符号的字符串的结果。
print(x ^ y) print(bin(x ^ y)) # 3 # 0b11
逻辑AND、OR和XOR的每一位的输入和输出的关系如下表所示。
输入1 | 输入2 | 交叉点 (AND) | 分歧点 (OR) | 排他性-OR操作 (XOR) |
---|---|---|---|---|
1 | 1 | 1 | 1 | 0 |
1 | 0 | 0 | 1 | 1 |
0 | 1 | 0 | 1 | 1 |
0 | 0 | 0 | 0 | 0 |
对负整数的位操作
当对一个负整数进行位操作时,该值的处理就像它以2的补码形式表示一样。
然而,请注意,如果你用bin()或format()将一个负整数转换为二进制字符串,绝对值将有一个减号,而不是二进制补码的格式。
如果你想得到一个用二补表示的字符串,就用所需的最大位数进行AND,如下图所示。
- 对于4位
0b1111
(=0xf
) - 对于8位
0xff
- 对于16位
0xffff
你可以得到一串二进制的补码表示(每个比特都被倒置,并加上1)。
x = -9 print(x) print(bin(x)) # -9 # -0b1001 print(bin(x & 0xff)) print(format(x & 0xffff, 'x')) # 0b11110111 # fff7
位数翻转 : ~经营者
~用运算符翻转位子的例子。
位反转并不是简单地将每个位的值反转。使用该运算符时的返回值如下。~x
=-(x+1)
-(x+1)
这个值相当于把输入值x看成是二的补码形式,并把所有的位都倒置。
如上所述,在Python中,当一个负整数使用bin()、format()等转换为二进制字符串时,它不是以二补的形式,而是以带减号的绝对值。因此,直接将 ~x 转换为字符串不会产生一个将原值的位数倒置的字符串。
x = 9 # 0b1001 print(~x) print(bin(~x)) # -10 # -0b1010
当我们进行AND操作并将其转化为一串二的补码表示时,我们可以看到原值的比特被倒置了。
此外,例如,为了得到一个4位数的位串,按原样倒置(省略符号位),使用format()为ANDed值填入0,如下所示'04b'
print(bin(~x & 0xff)) print(format(~x & 0b1111, '04b')) # 0b11110110 # 0110
位移 : << , >>
使用位移运算符进行左位移和右位移的例子。
x = 9 # 0b1001 print(x << 1) print(bin(x << 1)) # 18 # 0b10010 print(x >> 1) print(bin(x >> 1)) # 4 # 0b100
对于负值,符号位被扩展和移位,而正负符号保持不变。负值是一路向左的1行的图像。
x = -9 print(bin(x)) print(bin(x & 0xff)) # -0b1001 # 0b11110111 print(x << 1) print(bin(x << 1)) print(bin((x << 1) & 0xff)) # -18 # -0b10010 # 0b11101110 print(x >> 1) print(bin(x >> 1)) print(bin((x >> 1) & 0xff)) # -5 # -0b101 # 0b11111011
最好用二补表达式的字符串来思考,因为用数字来思考并不清楚。