python虽然是很高级的脚本语言,也还是对位运算有足够的支持。当我们需要的代码功能比较底层的时候,就需要使用到这些位运算。本文介绍python支持的6种位运算!
与 & AND
符号&实现与(AND)运算。
>>> 1 & 2
0
>>> bin(1)
'0b1'
>>> bin(2)
'0b10'
>>> 0b11010010 & 0b01010101
80
与运算的结果,会按照int类型显示出来。不过,需要注意一个细节,python中的int整数,不存在范围限制,即底层并没有固定使用多少个byte来存储。因此,在进行&运算的时候,python解释器默认会采用最长byte的方式来进行运算:
>>> 256 & 1 # 256 needs 2 bytes
0
>>> 255 & 1
1
>>> 65536 & 1 # 65536 need 3 bytes
0
>>> 65536 & 256
0
>>> 65536 & 65535
0
>>> 65535 & 65535
65535
有负数参与时:
>>> -1 & 2
2
>>>
>>> bin(-1 & 0xFF) # check -1's binary code
'0b11111111'
>>> bin(2)
'0b10'
计算机存储整数的方式是补码!正数的补码就是它自己,负数的补码是其对应的绝对值数的二进制码取反再加1。-1在计算机中的二进制码为 0b11111111,与2得到的结果是 0b00000010,还是2。
或 | OR
符号 | 实现或 OR 运算。
>>> 2 | 4
6
>>> bin(2)
'0b10'
>>> bin(4)
'0b100'
当数值需要的byte数不等时,同样是采用最长byte的方式来运算OR:
>>> 256 | 1
257
>>> 65536 | 1
65537
下面是有负数是的情况,跟&运算一样,都是直接采用负数的补码来计算:
>>> -1 | 2
-1
>>> bin(-1 & 0xFF)
'0b11111111'
>>> bin(2)
'0b10'
>>> -1 | -2
-1
>>> bin(-2 & 0xFF)
'0b11111110'
非 ~ NOT
符号 ~ 用来进行非运算。
>>> ~1
-2
>>> bin(~1 & 0xFF)
'0b11111110'
>>> ~-2
1
>>> bin(~-2 & 0xFF)
'0b1'
有了~运算,就可以计算补码,请参考:python中反码和补码的计算
异或 ^ XOR
符号 ^ 用来进行异或 XOR 操作。(计算机内部做加法的时候,用XOR来获得sum bit,用AND来获得 carry bit)
>>> 1^0
1
>>> 1^1
0
>>> 0^1
1
>>> 0^0
0
>>> 123^234
145
>>> bin(123)
'0b1111011'
>>> bin(234)
'0b11101010'
>>> bin(145)
'0b10010001'
当异或两边的数据对应的byte数不一样时,依然以大的那个为准:
>>> 256 ^ 255
511
>>> 65536 ^ 1
65537
>>> 65535 ^ 1
65534
带符号左移 <<
符号 << 用来进行bit的左移操作。
>>> 1<<1
2
>>> 1<<2
4
>>> 1<<3
8
>>> 1<<4
16
>>> -1<<1
-2
>>> -1<<2
-4
>>> -1<<3
-8
>>> -1<<4
-16
>>> bin(-1 & 0xFF)
'0b11111111'
>>> bin(-2 & 0xFF)
'0b11111110'
>>> bin(-4 & 0xFF)
'0b11111100'
>>> bin(-8 & 0xFF)
'0b11111000'
>>> bin(-16 & 0xFF)
'0b11110000'
移出来的空位,用0填充。是这样吗?我们继续左移-1试试看吧:
>>> -1<<5
-32
>>> -1<<6
-64
>>> -1<<7
-128
>>> -1<<8
-256
>>> bin(-256 & 0xFFFF)
'0b1111111100000000'
>>> -1<<16
-65536
>>> bin(-65536 & 0xFFFFFF)
'0b111111110000000000000000'
当把-1左移8位的时候,低8位就全部是0了,这时计数是继续的,-128再左移1位,应该得到-256,这就是带符号左移的含义!符号位被移动到第9个bit,因为它是符号位,所以它应该在高自己的最高位,在此符号位的移动过程中,中间的bit全部位置1,正好符合了补码的要求。
带符号右移 >>
符号 >> 用来进行右移运算。
>>> -1 >> 1
-1
>>> -1 >> 2
-1
>>> -1 >> 3
-1
>>> -1 >> 4
-1
0b11111111右移不变,因为要带符号,其实是符号位保持不动的结果。
>>> 128 >> 1
64
>>> 128 >> 2
32
>>> 128 >> 3
16
>>> 128 >> 4
8
>>> 128 >> 5
4
>>> 128 >> 6
2
>>> 128 >> 7
1
>>> 128 >> 8
0
>>> 128 >> 9
0
总结一下:
首先要理解,整数在计算中,是以补码的形式存在;
python所有的位操作,都是以补码为基础,这个细节特别是在有负数参与的时候,要注意,这一点与C语言也是一致的;
当两个整数实际所占用的byte数不一致时,以大的那个为准;
左移和右移,都是带符号的;
python位运算如果有负数参数,最后得到的结果如果依然是负数(最高位是1),解释器就显示位负数,否则就显示位整数。
-- EOF --