page contents

Python位运算符详解

Python位运算按照数据在内存中的二进制位(Bit)进行操作,它一般用于底层开发(算法设计、驱动、图像处理、单片机等),在应用层开发(Web 开发、Linux 运维等)中并不常见。

Python 位运算符只能用来操作整数类型,它按照整数在内存中的二进制形式进行计算。Python 支持的位运算符如表 1 所示。

&按位与a & b4 & 5
|按位或a | b4 | 5
^按位异或a ^ b4 ^ 5
~按位取反~a~4
<<按位左移a << b4 << 2,表示整数 4 按位左移 2 位
>>按位右移a >> b4 >> 2,表示整数 4 按位右移 2 位

& 按位与运算符

按位与运算符&的运算规则是:只有参与&运算的两个位都为 1 时,结果才为 1,否则为 0。例如1&1为 1,0&0为 0,1&0也为 0,这和逻辑运算符&&非常类似。

000
010
100
111


例如,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 代码对上面的分析进行验证:

  1. n = 0X8FA6002D
  2. print("%X" % (9&5) )
  3. print("%X" % (-9&5) )
  4. print("%X" % (n&0XFFFF) )

运行结果:
1
5
2D

| 按位或运算符

按位或运算符|的运算规则是:两个二进制位有一个为 1 时,结果就为 1,两个都为 0 时结果才为 0。例如1|1为 1,0|0为0,1|0 为1,这和逻辑运算中的||非常类似。

000
011
101
111


例如,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 代码对上面的分析进行验证:

  1. n = 0X2D
  2. print("%X" % (9|5) )
  3. print("%X" % (-9|5) )
  4. print("%X" % (n|0XFFFF0000) )

运行结果:
D
-9
FFFF002D

^按位异或运算符

按位异或运算^的运算规则是:参与运算的两个二进制位不同时,结果为 1,相同时结果为 0。例如0^1为 1,0^0为 0,1^1为 0。

000
011
101
110


例如,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 代码对上面的分析进行验证:

  1. n = 0X0A07002D
  2. print("%X" % (9^5) )
  3. print("%X" % (-9^5) )
  4. print("%X" % (n^0XFFFF0000) )

运行结果:
C
-E
F5F8002D

~按位取反运算符

按位取反运算符~为单目运算符(只有一个操作数),右结合性,作用是对参与运算的二进制位取反。例如~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 代码对上面的分析进行验证:

  1. print("%X" % (~9) )
  2. print("%X" % (~-9) )

运行结果:
-A
8

<<左移运算符

Python 左移运算符<<用来把操作数的各个二进制位全部左移若干位,高位丢弃,低位补 0。

例如,9<<3可以转换为如下的运算:

<< 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 代码对上面的分析进行验证:

  1. print("%X" % (9<<3) )
  2. 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 代码对上面的分析进行验证:

  1. print("%X" % (9>>3) )
  2. print("%X" % ((-9)>>3) )

运行结果:
1
-2

  • 发表于 2021-06-25 21:13
  • 阅读 ( 580 )
  • 分类:Python开发

0 条评论

请先 登录 后评论
Cara
Cara

36 篇文章

作家榜 »

  1. 轩辕小不懂 2403 文章
  2. 小柒 1324 文章
  3. Pack 1135 文章
  4. Nen 576 文章
  5. 王昭君 209 文章
  6. 文双 71 文章
  7. 小威 64 文章
  8. Cara 36 文章