python

关注公众号 jb51net

关闭
首页 > 脚本专栏 > python > numpy位运算怎么用

numpy位运算怎么用?bitwise_and按位与实例详解

作者:景早

想彻底搞懂NumPy位运算吗?本文详细介绍了bitwise_and、bitwise_or、bitwise_xor、invert、left_shift和right_shift等函数的用法,并通过实例解析按位与、按位取反、左移右移等操作,助你高效处理大规模数据,轻松掌握状态标志位控制和性能优化技巧

位运算是直接对二进制数字的位级别进行操作的运算方式,不依赖数字的整体十进制值。

NumPy 提供了一套高效的位运算工具,支持对数组元素进行矢量化逐位操作,性能远超 Python 原生位运算(尤其处理大规模数据时),广泛应用于底层数据优化、状态标志处理、数据压缩等场景。

一、核心概念与优势

NumPy 优势:

  1. 矢量化处理:直接作用于数组整体,无需循环遍历元素。
  2. 多类型支持:兼容整数、布尔值等多种数据类型。
  3. 性能优化:基于 C 语言实现,运算速度快。

NumPy 位运算函数均以 bitwise_ 开头,同时支持与 Python 原生位运算符对应的简写形式。

二、NumPy 位运算核心函数与运算符总览

下表完整梳理了 NumPy 中所有位运算的函数、对应运算符及核心功能:

操作类型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)~对数字每一位取反(0→1,1→0),有符号数需考虑补码规则
左移numpy.left_shift(x1, x2)<<将 x1 的二进制位向左移 x2 位,右侧补 0
右移numpy.right_shift(x1, x2)>>将 x1 的二进制位向右移 x2 位,左侧根据符号位补 0 或 1(正数补 0)

三、各运算详细用法与实例

1. 按位与(bitwise_and / &)

运算规则

两数对应二进制位均为 1 时结果为 1,否则为 0。规则表如下:

ABAND 结果
111
100
010
000

实例:整数与数组运算

import numpy as np

# 单个整数运算
a, b = 13, 17
print(f"13 的二进制:{bin(a)},17 的二进制:{bin(b)}")  # 0b1101 0b10001
print("按位与结果:", np.bitwise_and(a, b))  # 等价于 13 & 17,输出 1

# 数组运算(矢量化)
arr1 = np.array([13, 25], dtype=int)
arr2 = np.array([17, 10], dtype=int)
print("数组按位与:", arr1 & arr2)  # 输出 [1  8]

运算过程解析(13 & 17)

对齐二进制位后逐位计算:

  01101  (13)
& 10001  (17)
= 00001  (1)

2. 按位或(bitwise_or / |)

运算规则

两数对应二进制位有一个为 1 时结果为 1,否则为 0。规则表如下:

ABOR 结果
111
101
011
000

实例:整数运算

import numpy as np

a, b = 13, 17
print(f"13 的二进制:{bin(a)},17 的二进制:{bin(b)}")  # 0b1101 0b10001
print("按位或结果:", np.bitwise_or(a, b))  # 等价于 13 | 17,输出 29

运算过程解析(13 | 17)

  01101  (13)
| 10001  (17)
= 11101  (29)

3. 按位异或(bitwise_xor / ^)

运算规则

两数对应二进制位不同时结果为 1,相同时为 0。

实例:布尔数组运算

异或在布尔值上等价于 “逻辑异或”(True 为 1,False 为 0):

import numpy as np

arr1 = np.array([True, False, True], dtype=bool)
arr2 = np.array([False, True, False], dtype=bool)

# 函数与运算符等价
result1 = np.bitwise_xor(arr1, arr2)
result2 = arr1 ^ arr2

print("异或结果:", result1)  # 输出 [ True  True  True]
print("结果一致:", np.array_equal(result1, result2))  # 输出 True

4. 按位取反(invert / ~)

关键说明

实例 1:无符号整数取反

import numpy as np

# uint8 类型(0-255,8位二进制)
x = np.array([13], dtype=np.uint8)
x_invert = np.invert(x)

print(f"13 的 8 位二进制:{np.binary_repr(13, width=8)}")  # 00001101
print(f"取反后的值:{x_invert[0]}")  # 242
print(f"242 的 8 位二进制:{np.binary_repr(242, width=8)}")  # 11110010

实例 2:有符号整数取反

import numpy as np

x = 5  # 默认 int 类型(32位)
x_invert = ~x

print(f"5 的二进制(简化):00000101")
print(f"~5 的二进制(补码):11111010")
print(f"~5 的十进制:{x_invert}")  # 输出 -6

补码计算步骤(以~1 为例)

  1. 原码:1 → 00000001(8 位有符号);
  2. 逐位取反:11111110(符号位为 1,代表负数);
  3. 求补码(除符号位外取反 +1):10000001 + 1 = 10000010;
  4. 转换为十进制:-2。

5. 左移(left_shift / <<)

运算规则

将数字的二进制位向左移动指定位数,右侧用 0 填充。等价于乘以 2 的 n 次方(n 为移位数)。

实例

import numpy as np

x = 10  # 二进制:00001010
shifted = np.left_shift(x, 2)  # 等价于 10 << 2

print(f"10 左移 2 位结果:{shifted}")  # 输出 40
print(f"40 的二进制:{np.binary_repr(40, width=8)}")  # 00101000

原理

10 << 2 即二进制 00001010 左移 2 位 → 00101000(40),对应数学运算 10 × 2² = 40。

6. 右移(right_shift / >>)

运算规则

将数字的二进制位向右移动指定位数,左侧根据符号位补 0(正数)或 1(负数)。等价于整除 2 的 n 次方(n 为移位数)。

实例

import numpy as np

x = 40  # 二进制:00101000
shifted = np.right_shift(x, 2)  # 等价于 40 >> 2

print(f"40 右移 2 位结果:{shifted}")  # 输出 10
print(f"10 的二进制:{np.binary_repr(10, width=8)}")  # 00001010

原理

40 >> 2 即二进制 00101000 右移 2 位 → 00001010(10),对应数学运算 40 ÷ 2² = 10。

四、运算符使用注意事项

  1. 优先级问题:位运算符优先级低于算术运算符,计算时建议加括号。例:10 & 1 + 2 等价于 10 & 3(结果 2),而非 (10 & 1) + 2(结果 2)。
  2. 数组兼容性:参与运算的数组需满足 NumPy 的 “广播规则”(如形状一致或可广播)。
  3. 数据类型影响:取反运算的结果受数组 dtype 影响(无符号 vs 有符号),需明确指定类型避免歧义。

五、典型应用场景

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

六、总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

您可能感兴趣的文章:
阅读全文