位操作
Overview
python位操作仅支持int对象。
Operator | Example | Meaning | ||
---|---|---|---|---|
& | a & b | Bitwise AND | ||
a | b | Bitwise OR | ||
^ | a ^ b | Bitwise XOR (exclusive OR) | ||
~ | ~a | Bitwise NOT | ||
« | a « n | Bitwise left shift | ||
» | a » n | Bitwise right shift |
两大类型,逻辑操作和移位操作。
没有类似java的”»>”,无符号右移。
也可以复合操作
Operator | Example | Equivalent to | |||
---|---|---|---|---|---|
&= | a &= b | a = a & b | |||
= | a | = b | a = a | b | |
^= | a ^= b | a = a ^ b | |||
«= | a «= n | a = a « n | |||
»= | a »= n | a = a » n |
二进制表示
At the end of the day, everything is a number.
int的bit位:
(42).bit_length()
Unsigned Integers
python没有原生的无符号整型,可以用ctypes
模块引入。
>>> from ctypes import c_uint8 as unsigned_byte
>>> unsigned_byte(-42).value
214
以上-42被当作无符号整型解析。
Signed Integers
sign-magnitude表示法
首位是符号位,其余位一样,正负是对齐的,0的表示有两种。最大的问题是,算数变得复杂。
two’s complement表示法
用2的补码表示,整数的补码是原码,负数的补码是反码+1。
补码表示形式,最左侧的符号位,即表示符号,也表示幅度。如:
```Plain Text 补码:0b 1101 0110 表示:(-1) 0b 0010 1010,即-42 -42 = -128 + 64 + 16 + 4 + 2
整数的二进制bit字符串可以用`bin()`方法获得,该方法打印sign- magnitude表示结果。
## Integers In Python
CPython中,-5和256会在解释器初始化时就保存到缓存中,作为单例变量。
固定精度的整数采用`long` 数据结构,8个字节,对应2的补码存储,
任意精度的整数,采用中间层表示,对应sign-magnitude形式存储。
固定精度和任意精度之间解释器内部自动转换。
在Python中,Integers的符号位和模分开保存。
## 位逻辑操作
防止出错,避免用位逻辑操作(&, |, \~)替代逻辑操作(and, or , not)。
Bitwise AND
短的操作数左边补0.
Bitwise XOR
没有对应的普通逻辑操作,可模拟:
```python
def xor(a, b):
return (a and not b) or (not a and b)
移位操作
Left Shift
左移n位相当于放大2的n次方倍。
python存储整数是“无限长”,左移相当于将整数的二进制流变长,如果想得到和java、c++一样的效果,可以通过bitmask限制。
>>> 39 << 3
312
>>> (39 << 3) & 255
56
Right Shift
右移n位相当于对2的n次方进行地板除。
算数右移 vs 逻辑右移
逻辑右位又称无符号右移»>,即将整个二进制流右移,并在左侧补零,会导致符号位翻转。
python的整数不定长,没有定义无符号右移»>。
算数右移保留符号位,其余位右移,左侧补符号位相同的值(0或1)。这将使无论正负,右移操作都等价于地板除。
Bitmasks
获取某位
>> 和 &
>>> def get_normalized_bit(value, bit_index):
... return (value >> bit_index) & 1
...
>>> get_normalized_bit(0b10000000, bit_index=5)
0
>>> get_normalized_bit(0b10100000, bit_index=5)
1
某位置为1
« 和 |
>>> def set_bit(value, bit_index):
... return value | (1 << bit_index)
...
>>> set_bit(0b10000000, bit_index=5)
160
>>> bin(160)
'0b10100000'
某位置为0
«、|和 &
>>> def clear_bit(value, bit_index):
... return value & ~(1 << bit_index)
...
>>> clear_bit(0b11111111, bit_index=5)
223
>>> bin(223)
'0b11011111'
某位取反
« 和 ^
>>> def toggle_bit(value, bit_index):
... return value ^ (1 << bit_index)
...
>>> x = 0b10100000
>>> for _ in range(5):
... x = toggle_bit(x, bit_index=7)
... print(bin(x))
...
0b100000
0b10100000
0b100000
0b10100000
0b100000`