# 传统写法
defis_odd(n):
returnn%2==1
# 位运算写法(效率更高)
defis_odd_bit(n):
returnn&1==1# 与1相与,只看最后一位
# 练习:判断 7 和 10 的奇偶性
print(7&1) # 1 → 奇数
print(10&1) # 0 → 偶数
# 一行代码判断
print("奇数"if7&1else"偶数")
原理:二进制末位为1是奇数,为0是偶数。& 1 操作只保留最后一位。
# 左移 << 相当于乘以2的n次方
a=5
print(a<<1) # 10 (5×2)
print(a<<2) # 20 (5×4)
# 右移 >> 相当于除以2的n次方(整数)
b=20
print(b>>1) # 10 (20÷2)
print(b>>2) # 5 (20÷4)
# ⚠️ 练习:用位运算实现乘以8
defmultiply_by_8(n):
returnn<<3# 2³ = 8
# 验证
print(multiply_by_8(7)) # 56
a, b=5, 3
print(f"交换前: a={a}, b={b}")
# Python传统写法(直接解包)
# a, b = b, a
# 位运算方式(异或^)
a=a^b# a = 5^3 = 6 (110)
b=a^b# b = 6^3 = 5 (101) → 原来的a
a=a^b# a = 6^5 = 3 (011) → 原来的b
print(f"交换后: a={a}, b={b}")
# 练习:解释为什么异或能交换?
# 提示:a^a=0, a^0=a,异或满足交换律和结合律
# 定义权限常量(2的幂次,确保二进制只有一位是1)
READ=1<<0# 0001 = 1
WRITE=1<<1# 0010 = 2
EXECUTE=1<<2# 0100 = 4
DELETE=1<<3# 1000 = 8
# 给用户授权(用或运算|组合权限)
user_permission=READ|WRITE# 0011 = 3
# 检查是否有某权限(用与运算&)
defhas_permission(user_perm, perm):
return (user_perm&perm) ==perm
# 练习场景
print(has_permission(user_permission, READ)) # True
print(has_permission(user_permission, DELETE)) # False
# 移除权限(用与非运算)
user_permission&=~WRITE# 移除写权限
print(has_permission(user_permission, WRITE)) # False
# 添加权限
user_permission|=DELETE# 添加删除权限
print(bin(user_permission)) # 0b1001
defis_power_of_two(n):
"""
2的幂二进制特点:只有一位是1(如 1000, 100, 10, 1)
n & (n-1) 会将最低位的1变成0
"""
returnn>0and (n& (n-1)) ==0
# 验证
print(is_power_of_two(8)) # True (1000)
print(is_power_of_two(7)) # False (0111)
print(is_power_of_two(1)) # True (1)
print(is_power_of_two(0)) # False
# 练习:解释 8 & 7 的结果
# 8 = 1000, 7 = 0111 → 1000 & 0111 = 0000
print(f"8 & 7 = {8&7}") # 0
color=0xFF5733# 十六进制颜色值
# 提取红色通道(右移16位,取低8位)
r= (color>>16) &0xFF# 255
# 提取绿色通道(右移8位,取低8位)
g= (color>>8) &0xFF# 87
# 提取蓝色通道(直接取低8位)
b=color&0xFF# 51
print(f"RGB({r}, {g}, {b})") # RGB(255, 87, 51)
# 练习:将 RGB(100, 150, 200) 合并为十六进制
defrgb_to_hex(r, g, b):
return (r<<16) | (g<<8) |b
hex_color=rgb_to_hex(100, 150, 200)
print(f"0x{hex_color:06X}") # 0x6496C8
print(f"#{hex_color:06X}") # #6496C8
defcount_ones(n):
"""统计整数二进制表示中1的个数"""
count=0
whilen:
n&= (n-1) # 消除最低位的1
count+=1
returncount
# 验证
print(count_ones(0b1011)) # 3
print(count_ones(0b1000)) # 1
# Python内置方法(面试时展示了解)
print(bin(0b1011).count('1')) # 3
# 进阶:使用Brian Kernighan算法
defcount_ones_bk(n):
count=0
whilen:
n&=n-1# 关键操作:每次消除最右边的1
count+=1
returncount
classSimpleBloomFilter:
"""简单布隆过滤器:用位数组判断元素可能存在/肯定不存在"""
def__init__(self, size=32):
self.bits=0# 用整数模拟位数组
def_hash(self, s, seed):
"""简单哈希函数"""
h=seed
forcharins:
h= ((h<<5) -h) +ord(char)
returnabs(h) %32
defadd(self, item):
"""添加元素(设置对应位为1)"""
h1=self._hash(item, 1)
h2=self._hash(item, 2)
self.bits|= (1<<h1)
self.bits|= (1<<h2)
defmight_contain(self, item):
"""查询(如果对应位都是1,可能存在)"""
h1=self._hash(item, 1)
h2=self._hash(item, 2)
mask= (1<<h1) | (1<<h2)
return (self.bits&mask) ==mask
# 练习演示
bf=SimpleBloomFilter()
bf.add("apple")
bf.add("banana")
print(bf.might_contain("apple")) # True(一定存在)
print(bf.might_contain("banana")) # True(一定存在)
print(bf.might_contain("grape")) # False(肯定不存在)或 True(误判)
print(f"内部状态: {bin(bf.bits)}")
# Python的整数是无限精度的,~n = -n-1
print(~5) # -6
print(~-5) # 4
# 原理:按位取反,包括符号位
# 5 = ...00000101
# ~5 = ...11111010 = -6(补码表示)
# 如果需要固定8位取反(如图像处理)
definvert_8bit(n):
return (~n) &0xFF# 只保留低8位
print(invert_8bit(5)) # 250 (11111010)
print(invert_8bit(0)) # 255
print(invert_8bit(255)) # 0
选择题(答案在评论区置顶):
15 & 9 的结果是?
A. 6 B. 9 C. 15 D. 0
如何用位运算判断一个数是4的倍数?
提示:n & ? == 0
~0 在Python中的结果是?
A. 0 B. 1 C. -1 D. 255
编程挑战:
# 挑战1:不用算术运算符实现加法
defadd_without_plus(a, b):
# 提示:异或算无进位加法,与运算算进位
pass
# 挑战2:找出数组中唯一出现一次的数(其他都出现两次)
deffind_single(nums):
# 提示:利用 a ^ a = 0
pass