一、位运算基础概念
位运算直接对二进制位(bit)进行操作,运算速度远超加减乘除等算术运算。Python中的整数以二进制补码形式存储,所有位运算都基于补码完成。
二、按位运算符详解
1. 按位与 (&)
原理 :两个对应位都为1时结果为1,否则为0。
语法 :a & b
示例:
python
6的二进制是 0110,3的二进制是0011
print(6 & 3) # 输出 2,二进制结果为0010
典型应用:
- 快速判断奇偶:
x & 1若结果为1则是奇数,为0则是偶数 - 提取二进制特定位:
num & 0b1000提取第4位的值
2.按位或 (|)
原理 :只要有一个对应位为1,结果就为1。
语法 :a | b
示例:
python
# 6的二进制是0110,3的二进制是0011
print(6 | 3) # 输出7,二进制结果为0111
典型应用:
- 批量设置二进制位:
flags | 0b100开启第三位标志位 - 权限合并:将多个权限掩码合并为单一权限值
3. 按位异或 (^)
原理 :对应位相异时结果为1,相同时结果为0。
语法 :a ^ b
示例:
python
# 6的二进制是0110,3的二进制是0011
print(6 ^ 3) # 输出5,二进制结果为0101
典型应用:
- 变量交换(无需临时变量):a, b = a^b, b^a
- 快速定位不同:对比两个二进制数据的差异位
- 简单加密:使用同一个密钥对数据进行加解密
4.按位取反 (~)
原理 :对每个位取反,0变1,1变0。由于Python使用无限精度补码,结果表现为 ~x = -x-1
语法 :~a
示例:
python
print(~3) # 输出-4
# 3--011
# 4--100
典型应用:
- 生成掩码:
~0可以生成全1的二进制序列 - 快速获取负数表示:
~x +1等价于 -x
5.左移 (<<)
原理 :将二进制位向左移动n位,右边补0,相当于乘以2的n次方。
语法 :a << n
示例:
python
print(5 << 2) # 5的二进制是101,左移2位后变为10100,输出20
典型应用:
- 快速乘法:x << 1 等价于x*2
- 快速计算2的幂次:1 << n
6.右移 (>>)
原理 :将二进制位向右移动n位,正数左边补0,负数左边补1。相当于除以2的n次方并向下取整。
语法 :a >> n
示例:
python
print(20 >> 2) # 20的二进制是10100,右移2位后变为101,输出5
print(-20 >> 2) # 输出-5
典型应用:
- 快速除法:x >> 1 等价于x//2
- 取绝对值优化:对于负数 (x ^ (x >> 31)) - (x >>31)
三、高级应用技巧
1、位掩码操作
python
# 定义权限掩码
PERM_READ = 0b0001
PERM_WRITE = 0b0010
PERM_EXECUTE = 0b0100
# 分配权限
user_perm = PERM_READ | PERM_WRITE
# 检查权限
has_write = (user_perm & PERM_WRITE) != 0
2、快速计算奇偶与倍数
python
# 判断是否是2的幂
def is_power_of_two(x):
return x & (x-1) == 0
#这个函数的核心逻辑建立在2的幂的二进制特性之上:
# 2的幂的二进制特征:所有2的幂在二进制表示中,都只有最高位是1,其余位都是0。
# 2^0 = 1 → 二进制:0001
# 2^1 = 2 → 二进制:0010
# 2^2 = 4 → 二进制:0100
# 2^3 = 8 → 二进制:1000
# x-1的魔法翻转:当你对2的幂减1时,会把唯一的1变成0,并将它右边所有的0全部变成1。
# 8 (1000) -1 = 7 (0111)
# 4 (0100) -1 = 3 (0011)
# 位与运算消去1:将x和x-1进行位与运算时,两个数没有任何一位同时为1,所以结果必然是0。
# 1000 & 0111 = 0000
# 0100 & 0011 = 0000
#这个实现有一个需要注意的点:当x=0时,0 & (-1) 会等于0,但0并不是2的幂。在实际应用中,通常需要添加额外的判断条件:
def is_power_of_two(x):
return x > 0 and (x & (x-1)) == 0
# 计算两数平均值(避免溢出)
def average(a, b):
return (a + b) >> 1
3、IP地址转换
python
# 将IPv4地址转换为整数
#这个函数的本质是把点分十进制表示的IPv4地址,转换为一个32位无符号整数,利用位运算实现了最高效的合并。
def ip_to_int(ip):
# ip.split('.') 将字符串格式的IP地址按点分割,得到一个四元素字符串列表。比如输入 "192.168.1.1",会得到 ["192","168","1","1"]。
# map(int, ...) 将这四个字符串转换为整数类型,再用list()转为整数列表,最终 parts = [192,168,1,1]。
parts = list(map(int, ip.split('.')))
# parts[0] <<24:将IP的第一段(最高8位)左移24位,占据整数的最高8位。比如192 <<24 得到二进制中前8位为11000000,后面24位全是0。
# parts[1] <<16:第二段左移16位,占据第二高的8位。
# parts[2] <<8:第三段左移8位,占据第三组8位。
# parts[3]:第四段不移动,直接占据最后8位。
# 四次左移操作后,四段整数在二进制中各自占据独立的8位区域,使用|(按位或)将它们合并成一个完整的32位整数。按位或的特性保证了不同段的二进制位不会互相干扰,完美拼接四段8位数据。
return (parts[0] << 24) | (parts[1] <<16) | (parts[2]<<8) | parts[3]
位运算在Python标准库中的应用极其广泛,比如bisect模块的二分查找、array模块的内存优化、以及加密算法中的位级操作,深入掌握位运算能大幅提升你的代码执行效率与底层编程能力。