python中的位运算符

python中的位运算符

本文由gpt生成,仅作为本人自用的参考资料使用,不保证完全正确!

Python 中的位运算是非常常用且高效的操作,尤其在算法题、图论、压缩状态、权限管理等场景中非常有用。

1️⃣ 位运算符总览

运算符名称作用示例
(a = 0b0110​,b = 0b1011​)
结果(二进制)
&按位(AND)两位都为 1 ⇒ 1,否则 0a & b0b0010
|按位(OR)只要有一位为 1 ⇒ 1a | b0b1111
^按位异或(XOR)不同为 1,相同为 0a ^ b0b1101
~按位取反(NOT)0→1,1→0 (含符号位)~a…1111 1001​†
<<左移高位丢弃,低位补 0a << 20b11000
>>右移正数高位补 0;负数补 1b >> 10b0101

† 取反得到的是 无限长补码 表示;见下节说明。

另外:0b​ 是 Python 中表示 “二进制” 的前缀,0b中的0并不是符号位

特性一览,摘自​**力扣评论**​

  1. 与运算(AND):

    • 任何数和0做与运算,结果是0,即 x & 0 = 0

      例如,5(101) & 0 = 0。

    • 任何数和其自身做与运算,结果是自身,即 x & x = x

      例如,5(101) & 5(101) = 5(101)。

    • 用途:清除某些位,比如清除最低位:

      x & (x - 1)  # 去掉最低位的 1
      
  2. 或运算(OR):

    • 任何数和0做或运算,结果是自身,即 x | 0 = x

      例如,5(101) | 0 = 5(101)。

    • 任何数和其自身做或运算,结果是自身,即 x | x = x

      例如,5(101) | 5(101) = 5(101)。

    • 用途:设定某些位为 1

  3. 异或运算(XOR):

    • 任何数和0做异或运算,结果是自身,即 x ^ 0 = x

      例如,5(101) ^ 0 = 5(101)。

    • **任何数和其自身做异或运算,结果是0,即 x ^ x = 0**​

      例如,5(101) ^ 5(101) = 0。

    • 异或运算满足交换律和结合律,即 a ^ b ^ c = a ^ (b ^ c) = (a ^ b) ^ c

      例如,5(101) ^ 3(011) ^ 4(100) = 5 ^ (3 ^ 4) = (5 ^ 3) ^ 4。

    • 用途:

      • **消除重复元素:**​a ^ a = 0
      • **交换两个数:**​a ^= b; b ^= a; a ^= b
  4. 非运算(NOT):

    • 非运算会反转操作数的所有位,包括符号位。

    • 对整数 x​,返回 -(x+1)

      ~5  # = -6,因为:~x = -x - 1
      
  5. 左移运算(SHL):

    • 左移n位等于乘以2的n次方,即 x << n 等价于 x * 2^n

      例如,5(101) << 2 = 20(10100)。

    • x << k不会改变 x本身

    • 左移运算不改变操作数的符号位。

      • Python 的整数是无限精度的;
      • 所以左移只是不断乘以 2不会自动溢出或改变符号
  6. 右移运算(SHR):

    • 每右移 1 位,相当于 //2(向下取整)

      右移n位等于除以2的n次方,即 x >> n 等价于 x // 2^n

      例如,20(10100) >> 2 = 5(101)。

    • x >> k不会改变 x本身

    • 右移运算正数高位补 0;负数补 1

    • 右移并不会改变符号,Python 会保留负号


2️⃣ 负数与补码

Python 的整数没有位数上限,用二进制补码无限延伸。

  • e.g. x = -5​ → 内部补码为 …11111011
  • 所以 ~x​ 相当于 -(x+1)
x = -5
print(~x)        # 4
print(~4)        # -5

3️⃣ 进制转换与位处理辅助函数

函数 / 方法作用栗子
bin(x)​/oct(x)​/hex(x)转 2/8/16 进制字符串bin(10)​→'0b1010'
int(s, base)任意进制转十进制int('FF',16)​→255
int.bit_length()去掉符号位后所需位宽(1023).bit_length()​→10
int.bit_count()​(Py 3.8+)Hamming weight,统计 1 的个数(0b1011).bit_count()​→3
int.to_bytes()​/int.from_bytes()整数↔字节序列(255).to_bytes(2,'big')

4️⃣ 常见技巧 / 场景

✔️ 交换两数

a ^= b
b ^= a
a ^= b

✔️ 判断奇偶

x & 1 == 1  # 奇数
x & 1 == 0  # 偶数

✔ 检查第 k 位是否为 1(从右数起,0-based)

0-based 的意思是「从 0 开始编号」,位运算相关的最低位也就是第0位一般是最右边的那一位

(x >> k) & 1 == 1
# 或:
x & (1 << k) != 0

含义:

  1. x >> k​ 把第 k​ 位移到最右边
  2. & 1​ 只保留最右边那一位(高位如果还有1,就被消去了)
  3. 看它是不是等于 1

✔️ 清零 / 置位 / 翻转指定位

mask = 1 << k      # 第 k 位掩码 (0‑based),例如1 << 3 就等价于0b1000,第0位的1左移了三位抵达第k位
x |= mask          # 把第 k 位变成 1(无论原来是几)
x &= ~mask         # 把第 k 位清 0
x ^= mask          # 把第 k 位翻转(0→1, 1→0)

✔️ 提取低位 / 高位

low8  = x & 0xff   # 仅保留最低 8 位
high4 = (x >> 4) & 0xf

背后的思路:用掩码(mask)保留需要的位

1️⃣ 0xff​ 是什么?
0xff = 0b11111111 = 255

8 个 1​,用于掩盖(保留)最低 8 位。

x = 0b1011011100101101
x & 0xff = 仅保留最后 8 位,其它全部变 0

👉 所以 x & 0xff​ 就是 保留最低 8 位,其余清零

2️⃣ (x >> 4) & 0xf​ 是什么?
  • x >> 4​:将 x 向右移 4 位,相当于丢掉低 4 位;
  • & 0xf = 0b1111​:只保留当前最低的 4 位;
  • 所以它实际上是提取了 原来第 4~7 位 的内容。

✅ 举个例子

x = 0b10110110_00111100

low8 = x & 0xff        # 得到 0b00111100 = 0x3C = 60
high4 = (x >> 4) & 0xf # 移掉低 4 位再取低 4 位 = 0b0110 = 6

✔️ 子集枚举(按位集合的所有子集)

S = 0b10110 # 假设 S 表示一个集合
sub = S
while sub:
    # 处理子集 sub
    sub = (sub - 1) & S
🧠 这个技巧是干嘛的?

它是用来枚举一个集合(用位表示)的所有子集

  • 集合 S 用一个二进制数表示,比如 S = 0b10110​ 表示集合 {1, 2, 4}​,

    也就是第i​位若为1,代表i​在集合中;

  • 它的子集也用相同形式表示,比如 0b10010​ 表示 {1, 4}​;

  • 每次减 1 再与原集合相与,就能跳转到下一个有效子集

🔄 每一步发生了什么?
sub = S  # 从全集 S 开始
while sub:
    # 处理 sub,例如打印、统计等
    sub = (sub - 1) & S

这个过程枚举了 S 的所有非空子集,不重复、也不多余。

✅ 举个例子

假设 S = 0b110​,对应集合 {1, 2}​:

枚举过程如下:

stepsub (二进制)子集(集合)
1110{1, 2}
2101{0, 2}​❌不合法(超出 S)→ 被掩码去掉 →100{2}
3011{0, 1}​❌也不合法 → 掩码 →010{1}
4001{0}​❌ → 掩码 →000

5️⃣ 运算符优先级 & 结合律

  • 位运算符的优先级低于算术运算 + - *​,但高于比较运算 < > ==​。
  • 同一行里,~​ > << >>​ > &​ > ^​ > |​。
  • 全都是 左结合~​ 是单目)。
x = 1 << 3 + 1   # 等价于 1 << (3+1) → 16
y = 1 | 2 & 3    # 等价于 1 | (2 & 3) → 1|2 → 3

6️⃣ 小结

  • 与/或/异或/取反/移位 是位运算的核心。
  • 补码导致 ~x == -(x+1)​。
  • bit_length​&bit_count​、掩码技巧让位运算在性能与内存受限的场景(如算法竞赛、嵌入式、加密)非常有用。
  • 牢记优先级或加括号,避免坑。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值