查看: 252|回复: 0

NumPy位运算教程:bitwise_and按位与与移位取反

[复制链接]
发表于 2 小时前 | 显示全部楼层 |阅读模式
位运算直接操作二进制数的每一位,不依赖数字的十进制整体值。NumPy 把这类操作封装成矢量化函数,能直接作用于整个数组,底层由 C 实现,因此在处理大规模数据时通常比 Python 原生循环逐元素做位运算更高效。NumPy 位运算函数均以 bitwise_ 开头,同时也支持与 Python 原生位运算符对应的简写形式。

一、NumPy 位运算函数与运算符总览

按位与:numpy.bitwise_and(x1, x2),对应运算符 &,两数对应位均为 1 时结果为 1,否则为 0。
按位或:numpy.bitwise_or(x1, x2),对应运算符 |,两数对应位有一个为 1 时结果为 1,否则为 0。
按位异或:numpy.bitwise_xor(x1, x2),对应运算符 ^,两数对应位不同时结果为 1,相同时为 0。
按位取反:numpy.invert(x),对应运算符 ~,对数字每一位取反;有符号数需要结合补码规则理解。
左移:numpy.left_shift(x1, x2),对应运算符 <<,将 x1 的二进制位向左移动 x2 位,右侧补 0。
右移:numpy.right_shift(x1, x2),对应运算符 >>,将 x1 的二进制位向右移动 x2 位,左侧根据符号位补 0 或 1,正数补 0。

二、按位与 bitwise_and 与 & 的用法

按位与的规则是:1 & 1 = 1,1 & 0 = 0,0 & 1 = 0,0 & 0 = 0。
  1. import numpy as np
  2. # 单个整数运算
  3. a, b = 13, 17
  4. print(f"13 的二进制:{bin(a)},17 的二进制:{bin(b)}")  # 0b1101 0b10001
  5. print("按位与结果:", np.bitwise_and(a, b))  # 等价于 13 & 17,输出 1
  6. # 数组运算(矢量化)
  7. arr1 = np.array([13, 25], dtype=int)
  8. arr2 = np.array([17, 10], dtype=int)
  9. print("数组按位与:", arr1 & arr2)  # 输出 [1 8]
复制代码

13 的二进制为 01101,17 的二进制为 10001。按位对齐后逐位计算,结果为 00001,即十进制的 1。数组运算中,[13, 25] 与 [17, 10] 逐元素按位与,得到 [1, 8],这也是 NumPy 矢量化能力的直接体现。

三、按位或 bitwise_or 与 | 的用法

按位或的规则是:1 | 1 = 1,1 | 0 = 1,0 | 1 = 1,0 | 0 = 0。
  1. import numpy as np
  2. a, b = 13, 17
  3. print(f"13 的二进制:{bin(a)},17 的二进制:{bin(b)}")  # 0b1101 0b10001
  4. print("按位或结果:", np.bitwise_or(a, b))  # 等价于 13 | 17,输出 29
复制代码

13 | 17 的计算过程为:01101 与 10001 逐位或,得到 11101,即十进制 29。

四、按位异或 bitwise_xor 与 ^ 的用法

按位异或的规则是:两数对应位不同时结果为 1,相同时为 0。它同样适用于布尔数组,在布尔值上等价于逻辑异或,True 视为 1,False 视为 0。
  1. import numpy as np
  2. arr1 = np.array([True, False, True], dtype=bool)
  3. arr2 = np.array([False, True, False], dtype=bool)
  4. # 函数与运算符等价
  5. result1 = np.bitwise_xor(arr1, arr2)
  6. result2 = arr1 ^ arr2
  7. print("异或结果:", result1)  # 输出 [ True True True]
  8. print("结果一致:", np.array_equal(result1, result2))  # 输出 True
复制代码

上面两个布尔数组逐元素异或后,结果均为 True,并且函数调用与运算符写法的结果完全一致。

五、按位取反 invert 与 ~ 的用法

按位取反对数字的每一位执行 0 变 1、1 变 0。需要注意的是,结果受数组 dtype 影响:无符号整数直接逐位取反;有符号整数则要按二进制补码规则解释,最高位为符号位,0 表示正,1 表示负。

无符号整数取反示例:
  1. import numpy as np
  2. # uint8 类型(0-255,8位二进制)
  3. x = np.array([13], dtype=np.uint8)
  4. x_invert = np.invert(x)
  5. print(f"13 的 8 位二进制:{np.binary_repr(13, width=8)}")  # 00001101
  6. print(f"取反后的值:{x_invert[0]}")  # 242
  7. print(f"242 的 8 位二进制:{np.binary_repr(242, width=8)}")  # 11110010
复制代码

uint8 的 13 表示为 00001101,逐位取反后为 11110010,即十进制的 242。

有符号整数取反示例:
  1. import numpy as np
  2. x = 5  # 默认 int 类型(32位)
  3. x_invert = ~x
  4. print("5 的二进制(简化):00000101")
  5. print("~5 的二进制(补码):11111010")
  6. print(f"~5 的十进制:{x_invert}")  # 输出 -6
复制代码

以 ~1 为例说明补码计算步骤:1 的 8 位有符号原码为 00000001;逐位取反后为 11111110,此时符号位为 1,代表负数;再按补码规则处理,除符号位外取反加 1:10000001 + 1 = 10000010;转换为十进制即 -2。

六、左移 left_shift 与 << 的用法

左移将数字的二进制位向左移动指定位数,右侧用 0 填充,等价于乘以 2 的 n 次方,n 为移位数。
  1. import numpy as np
  2. x = 10  # 二进制:00001010
  3. shifted = np.left_shift(x, 2)  # 等价于 10 << 2
  4. print(f"10 左移 2 位结果:{shifted}")  # 输出 40
  5. print(f"40 的二进制:{np.binary_repr(40, width=8)}")  # 00101000
复制代码

10 的二进制为 00001010,左移 2 位后变为 00101000,即 40,对应数学运算 10 × 2² = 40。

七、右移 right_shift 与 >> 的用法

右移将数字的二进制位向右移动指定位数,左侧根据符号位补 0 或 1,正数补 0,等价于整除 2 的 n 次方。
  1. import numpy as np
  2. x = 40  # 二进制:00101000
  3. shifted = np.right_shift(x, 2)  # 等价于 40 >> 2
  4. print(f"40 右移 2 位结果:{shifted}")  # 输出 10
  5. print(f"10 的二进制:{np.binary_repr(10, width=8)}")  # 00001010
复制代码

40 的二进制为 00101000,右移 2 位后变为 00001010,即 10,对应数学运算 40 ÷ 2² = 10。

八、运算符使用注意事项

优先级问题:位运算符的优先级低于算术运算符,计算时建议加括号。例如 10 & 1 + 2 会先算 1 + 2 得到 3,再算 10 & 3,结果为 2;如果写成 (10 & 1) + 2,求值顺序不同,虽然该例结果碰巧也是 2,但不应依赖这种巧合。

数组兼容性:参与运算的数组需要满足 NumPy 的广播规则,即形状一致或可以广播。

数据类型影响:取反运算的结果受数组 dtype 影响,无符号类型与有符号类型的表现不同,实际使用时建议明确指定类型,避免歧义。

九、典型应用场景

底层数据处理:操作二进制文件中的字节数据,如图片、音频等。
状态标志位控制:用单个整数的不同位表示多个状态,例如用 0b101 表示 3 个状态的组合。
性能优化:用左移、右移替代乘法和除法,在部分场景下速度更快。
加密与校验:基于异或等运算实现简单的数据加密或校验,如 CRC 校验。

十、总结

NumPy 位运算围绕按位与、按位或、按位异或、按位取反、左移和右移展开,函数形式与运算符形式基本一一对应。实际编码时重点注意三点:位运算优先级低于算术运算,数组需要满足广播规则,取反结果受 dtype 影响。掌握这些细节后,就可以把位运算用于数组级二进制处理、状态标志管理和性能优化等场景。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

指导单位

江苏省公安厅

江苏省通信管理局

浙江省台州刑侦支队

DEFCON GROUP 86025

Hacking Group 021A

旗下站点

态势感知中心

应急响应中心

红盟安全

联系我们

官方QQ群:112851260

官方邮箱:security#ihonker.org(#改成@)

官方核心成员

关注微信公众号

Archiver|手机版|小黑屋| ( 沪ICP备2021026908号 )

GMT+8, 2026-9-29 13:38 , Processed in 0.021186 second(s), 18 queries , Gzip On, Redis On.

Powered by ihonker.com

Copyright © 2015-现在.

  • 返回顶部