NumPy 位运算
位运算是一种在二进制数字的位级别上进行操作的一类运算,它们直接操作二进制数字的各个位,而不考虑数字的整体值。
NumPy 提供了一系列位运算函数,允许对数组中的元素进行逐位操作,这些操作与 Python 的位运算符类似,但作用于 NumPy 数组,支持矢量化处理,性能更高。
位运算在计算机科学中广泛应用于优化和处理底层数据。
NumPy bitwise_ 开头的函数是位运算函数。
NumPy 位运算包括以下几个函数:
| 操作 | 函数/运算符 | 描述 |
|---|---|---|
| 按位与 |
numpy.bitwise_and(x1, x2)
|
对数组的每个元素执行逐位与操作。 |
| 按位或 |
numpy.bitwise_or(x1, x2)
|
对数组的每个元素执行逐位或操作。 |
| 按位异或 |
numpy.bitwise_xor(x1, x2)
|
对数组的每个元素执行逐位异或操作。 |
| 按位取反 |
numpy.invert(x)
|
对数组的每个元素执行逐位取反(按位非)。 |
| 左移 |
numpy.left_shift(x1, x2)
|
将数组的每个元素左移指定的位数。 |
| 右移 |
numpy.right_shift(x1, x2)
|
将数组的每个元素右移指定的位数。 |
importnumpyasnparr1=np.array([True,False,True],dtype=bool)arr2=np.array([False,True,False],dtype=bool)result_and=np.bitwise_and(arr1,arr2)result_or=np.bitwise_or(arr1,arr2)result_xor=np.bitwise_xor(arr1,arr2)result_not=np.bitwise_not(arr1)print("AND:",result_and)# [False, False, False]print("OR:",result_or)# [True, True, True]print("XOR:",result_xor)# [True, True, True]print("NOT:",result_not)# [False, True, False]# 按位取反arr_invert=np.invert(np.array([1,2],dtype=np.int8))print("Invert:",arr_invert)# [-2, -3]# 左移位运算arr_left_shift=np.left_shift(5,2)print("Left Shift:",arr_left_shift)# 20# 右移位运算arr_right_shift=np.right_shift(10,1)print("Right Shift:",arr_right_shift)# 5
也可以使用 "&"、 "~"、 "|" 和 "^" 等操作符进行计算:
-
与运算(&): 对应位上的两个数字都为1时,结果为1;否则,结果为0。
例如:1010 & 1100 = 1000
-
或运算(|): 对应位上的两个数字有一个为1时,结果为1;否则,结果为0。
例如:1010 | 1100 = 1110
-
异或运算(^): 对应位上的两个数字相异时,结果为1;相同时,结果为0。
例如:1010 ^ 1100 = 0110
-
取反运算(~): 对数字的每个位取反,即0变为1,1变为0。
例如:~1010 = 0101
-
左移运算(<<): 将数字的所有位向左移动指定的位数,右侧用0填充。
例如:1010 << 2 = 101000
-
右移运算(>>): 将数字的所有位向右移动指定的位数,左侧根据符号位或补零。
例如:1010 >> 2 = 0010
bitwise_and
bitwise_and() 函数对数组中整数的二进制形式执行位与运算。
importnumpyasnpprint('13 和 17 的二进制形式:')a,b=13,17print(bin(a),bin(b))print('\n')print('13 和 17 的位与:')print(np.bitwise_and(13,17))
输出结果为:
13 和 17 的二进制形式: 0b1101 0b10001 13 和 17 的位与: 1
以上实例可以用下表来说明:
| 1 | 1 | 0 | 1 | ||
|---|---|---|---|---|---|
| AND | |||||
| 1 | 0 | 0 | 0 | 1 | |
| 运算结果 | 0 | 0 | 0 | 0 | 1 |
位与操作运算规律如下:
| A | B | AND |
|---|---|---|
| 1 | 1 | 1 |
| 1 | 0 | 0 |
| 0 | 1 | 0 |
| 0 | 0 | 0 |
bitwise_or
bitwise_or()函数对数组中整数的二进制形式执行位或运算。
importnumpyasnpa,b=13,17print('13 和 17 的二进制形式:')print(bin(a),bin(b))print('13 和 17 的位或:')print(np.bitwise_or(13,17))
输出结果为:
13 和 17 的二进制形式: 0b1101 0b10001 13 和 17 的位或: 29
以上实例可以用下表来说明:
| 1 | 1 | 0 | 1 | ||
|---|---|---|---|---|---|
| OR | |||||
| 1 | 0 | 0 | 0 | 1 | |
| 运算结果 | 1 | 1 | 1 | 0 | 1 |
位或操作运算规律如下:
| A | B | OR |
|---|---|---|
| 1 | 1 | 1 |
| 1 | 0 | 1 |
| 0 | 1 | 1 |
| 0 | 0 | 0 |
invert
invert() 函数对数组中整数进行位取反运算,即 0 变成 1,1 变成 0。
对于有符号整数,取该二进制数的补码,然后 +1。二进制数,最高位为0表示正数,最高位为 1 表示负数。
看看 ~1 的计算步骤:
-
将
1(这里叫:原码)转二进制 =00000001 -
按位取反 =
11111110 -
发现符号位(即最高位)为
1(表示负数),将除符号位之外的其他数字取反 =10000001 -
末位加1取其补码 =
10000010 -
转换回十进制 =
-2
| 表达式 | 二进制值(2 的补数) | 十进制值 |
|---|---|---|
| 5 | 00000000 00000000 00000000 00000101 | 5 |
| ~5 | 11111111 11111111 11111111 11111010 | -6 |
importnumpyasnpprint('13 的位反转,其中 ndarray 的 dtype 是 uint8:')print(np.invert(np.array([13],dtype=np.uint8)))print('\n')# 比较 13 和 242 的二进制表示,我们发现了位的反转print('13 的二进制表示:')print(np.binary_repr(13,width=8))print('\n')print('242 的二进制表示:')print(np.binary_repr(242,width=8))
输出结果为:
13 的位反转,其中 ndarray 的 dtype 是 uint8: [242] 13 的二进制表示: 00001101 242 的二进制表示: 11110010
left_shift
left_shift() 函数将数组元素的二进制形式向左移动到指定位置,右侧附加相等数量的 0。
importnumpyasnpprint('将 10 左移两位:')print(np.left_shift(10,2))print('\n')print('10 的二进制表示:')print(np.binary_repr(10,width=8))print('\n')print('40 的二进制表示:')print(np.binary_repr(40,width=8))# '00001010' 中的两位移动到了左边,并在右边添加了两个 0。
输出结果为:
将 10 左移两位: 40 10 的二进制表示: 00001010 40 的二进制表示: 00101000
right_shift
right_shift() 函数将数组元素的二进制形式向右移动到指定位置,左侧附加相等数量的 0。
importnumpyasnpprint('将 40 右移两位:')print(np.right_shift(40,2))print('\n')print('40 的二进制表示:')print(np.binary_repr(40,width=8))print('\n')print('10 的二进制表示:')print(np.binary_repr(10,width=8))# '00001010' 中的两位移动到了右边,并在左边添加了两个 0。
输出结果为:
将 40 右移两位: 10 40 的二进制表示: 00101000 10 的二进制表示: 00001010