位运算这个概念大家可能比拟生疏,个别的数学运算中是看不到相似的概念的,所以本课内容有些形象,然而位运算在python应用层开发中使用的不多,个别与底层开发关系比拟亲密。所谓位运算指的是计算机依照数据在内存中的二进制位进行的运算操作。Python 位运算符(www.wakey.com.cn/document-seat.html)只能用来操作整数类型,它依照整数在内存中的二进制模式进行计算。本章内容看不懂的能够间接跳过。
一、位运算符
二、& 按位与运算符
按位与运算符&的运算规定是:只有参加&运算的两个位都为 1 时,后果才为 1,否则为 0。例如1&1为 1,0&0为 0,1&0也为 0,这和逻辑运算符&&十分相似。
表 2 Python & 运算符的规定
例如,9&5能够转换成如下的运算:
0000 0000 -- 0000 0000 -- 0000 0000 -- 0000 1001 (9 在内存中的存储)
& 0000 0000 -- 0000 0000 -- 0000 0000 -- 0000 0101 (5 在内存中的存储)
0000 0000 -- 0000 0000 -- 0000 0000 -- 0000 0001 (1 在内存中的存储)
&运算符会对参加运算的两个整数的所有二进制位进行&运算,9&5的后果为 1。
又如,-9&5能够转换成如下的运算:
1111 1111 -- 1111 1111 -- 1111 1111 -- 1111 0111 (-9 在内存中的存储)
& 0000 0000 -- 0000 0000 -- 0000 0000 -- 0000 0101 (5 在内存中的存储)
0000 0000 -- 0000 0000 -- 0000 0000 -- 0000 0101 (5 在内存中的存储)
-9&5的后果是 5。不理解整数在内存中如何存储的读者,请猛击:整数在内存中是如何存储的,为什么它堪称蠢才般的设计?
再强调一遍,&运算符操作的是数据在内存中存储的原始二进制位,而不是数据自身的二进制模式;其余位运算符也一样。以-9&5为例,-9 的在内存中的存储和 -9 的二进制模式截然不同:
1111 1111 -- 1111 1111 -- 1111 1111 -- 1111 0111 (-9 在内存中的存储)
-0000 0000 -- 0000 0000 -- 0000 0000 -- 0000 1001 (-9 的二进制模式,后面多余的0能够抹掉)
按位与运算通常用来对某些位清 0,或者保留某些位。例如要把 n 的高 16 位清 0 ,保留低 16 位,能够进行n & 0XFFFF运算(0XFFFF 在内存中的存储模式为 0000 0000 -- 0000 0000 -- 1111 1111 -- 1111 1111)。
应用 Python 代码对下面的剖析进行验证:
n = 0X8FA6002Dprint("%X" % (9&5) )print("%X" % (-9&5) )print("%X" % (n&0XFFFF) )运行后果:152D
三、| 按位或运算符
按位或运算符|的运算规定是:两个二进制位有一个为 1 时,后果就为 1,两个都为 0 时后果才为 0。例如1|1为 1,0|0为0,1|0 为1,这和逻辑运算中的||十分相似。
第一个Bit位 第二个Bit位 后果
0 0 0
0 1 1
1 0 1
1 1 1
例如,9 | 5能够转换成如下的运算:
0000 0000 -- 0000 0000 -- 0000 0000 -- 0000 1001 (9 在内存中的存储)
| 0000 0000 -- 0000 0000 -- 0000 0000 -- 0000 0101 (5 在内存中的存储)
0000 0000 -- 0000 0000 -- 0000 0000 -- 0000 1101 (13 在内存中的存储)
9 | 5的后果为 13。
又如,-9 | 5能够转换成如下的运算:
1111 1111 -- 1111 1111 -- 1111 1111 -- 1111 0111 (-9 在内存中的存储)
| 0000 0000 -- 0000 0000 -- 0000 0000 -- 0000 0101 (5 在内存中的存储)
1111 1111 -- 1111 1111 -- 1111 1111 -- 1111 0111 (-9 在内存中的存储)
-9 | 5的后果是 -9。
按位或运算能够用来将某些地位 1,或者保留某些位。例如要把 n 的高 16 地位 1,保留低 16 位,能够进行n | 0XFFFF0000运算(0XFFFF0000 在内存中的存储模式为 1111 1111 -- 1111 1111 -- 0000 0000 -- 0000 0000)。
应用 Python 代码对下面的剖析进行验证:
n = 0X2Dprint("%X" % (9|5))print("%X" % (-9|5))print("%X" % (n|0XFFFF0000))运行后果:D-9FFFF002D
四、^按位异或运算符
按位异或运算^的运算规定是:参加运算的两个二进制位不同时,后果为 1,雷同时后果为 0。例如0^1为 1,0^0为 0,1^1为 0。
第一个Bit位 第二个Bit位 后果
0 0 0
0 1 1
1 0 1
1 1 0
例如,9 ^ 5能够转换成如下的运算:
0000 0000 -- 0000 0000 -- 0000 0000 -- 0000 1001 (9 在内存中的存储)
^ 0000 0000 -- 0000 0000 -- 0000 0000 -- 0000 0101 (5 在内存中的存储)
0000 0000 -- 0000 0000 -- 0000 0000 -- 0000 1100 (12 在内存中的存储)
9 ^ 5的后果为 12。
又如,-9 ^ 5能够转换成如下的运算:
1111 1111 -- 1111 1111 -- 1111 1111 -- 1111 0111 (-9 在内存中的存储)
^ 0000 0000 -- 0000 0000 -- 0000 0000 -- 0000 0101 (5 在内存中的存储)
1111 1111 -- 1111 1111 -- 1111 1111 -- 1111 0010 (-14 在内存中的存储)
-9 ^ 5的后果是 -14。
按位异或运算能够用来将某些二进制位反转。例如要把 n 的高 16 位反转,保留低 16 位,能够进行n ^ 0XFFFF0000运算(0XFFFF0000 在内存中的存储模式为 1111 1111 -- 1111 1111 -- 0000 0000 -- 0000 0000)。
应用 Python 代码对下面的剖析进行验证:
n = 0X0A07002Dprint("%X" % (9^5) )print("%X" % (-9^5) )print("%X" % (n^0XFFFF0000) )运行后果:C-EF5F8002D
五、~按位取反运算符
按位取反运算符~为单目运算符(只有一个操作数),右联合性,作用是对参加运算的二进制位取反。例如~1为0,~0为1,这和逻辑运算中的!十分相似。
例如,~9能够转换为如下的运算:
~ 0000 0000 -- 0000 0000 -- 0000 0000 -- 0000 1001 (9 在内存中的存储)
1111 1111 -- 1111 1111 -- 1111 1111 -- 1111 0110 (-10 在内存中的存储)
所以~9的后果为 -10。
例如,~-9能够转换为如下的运算:
~ 1111 1111 -- 1111 1111 -- 1111 1111 -- 1111 0111 (-9 在内存中的存储)
0000 0000 -- 0000 0000 -- 0000 0000 -- 0000 1000 (8 在内存中的存储)
所以~-9的后果为 8。
应用 Python 代码对下面的剖析进行验证:
print("%X" % (~9) )print("%X" % (~-9) )运行后果:-A8
六、<<左移运算符
Python 左移运算符<<用来把操作数的各个二进制位全副左移若干位,高位抛弃,低位补 0。
<< 0000 0000 -- 0000 0000 -- 0000 0000 -- 0000 1001 (9 在内存中的存储)
0000 0000 -- 0000 0000 -- 0000 0000 -- 0100 1000 (72 在内存中的存储)
所以9<<3的后果为 72。
又如,(-9)<<3能够转换为如下的运算:
<< 1111 1111 -- 1111 1111 -- 1111 1111 -- 1111 0111 (-9 在内存中的存储)
1111 1111 -- 1111 1111 -- 1111 1111 -- 1011 1000 (-72 在内存中的存储)
所以(-9)<<3的后果为 -72
如果数据较小,被抛弃的高位不蕴含 1,那么左移 n 位相当于乘以 2 的 n 次方。
应用 Python 代码对下面的剖析进行验证:
print("%X" % (9<<3) )print("%X" % ((-9)<<3) )运行后果:48 -48
七、>>右移运算符
Python 右移运算符>>用来把操作数的各个二进制位全副右移若干位,低位抛弃,高位补 0 或 1。如果数据的最高位是 0,那么就补 0;如果最高位是 1,那么就补 1。
例如,9>>3能够转换为如下的运算:
0000 0000 -- 0000 0000 -- 0000 0000 -- 0000 1001 (9 在内存中的存储)
0000 0000 -- 0000 0000 -- 0000 0000 -- 0000 0001 (1 在内存中的存储)
所以9>>3的后果为 1。
又如,(-9)>>3能够转换为如下的运算:
1111 1111 -- 1111 1111 -- 1111 1111 -- 1111 0111 (-9 在内存中的存储)
1111 1111 -- 1111 1111 -- 1111 1111 -- 1111 1110 (-2 在内存中的存储)
所以(-9)>>3的后果为 -2
如果被抛弃的低位不蕴含 1,那么右移 n 位相当于除以 2 的 n 次方(但被移除的位中常常会蕴含 1)。
应用 Python 代码对下面的剖析进行验证:
print("%X" % (9>>3) )print("%X" % ((-9)>>3) )运行后果:1 -2