目录
- [Rust 位运算详解](#Rust 位运算详解)
-
- 一、与(AND)运算
-
- [1.1 Brian Kernighan 算法(布赖恩·克尼根算法)](#1.1 Brian Kernighan 算法(布赖恩·克尼根算法))
- 二、或(OR)运算
- 三、非(NOT)运算
- 四、异或(XOR)运算
-
- [4.1 运算规则](#4.1 运算规则)
- [4.2 运算法则](#4.2 运算法则)
- [五、左移(SHL,Shift Left)运算](#五、左移(SHL,Shift Left)运算)
- [六、右移(SHR,Shift Right)运算](#六、右移(SHR,Shift Right)运算)
- [七、Rust 中的位运算 Trait](#七、Rust 中的位运算 Trait)
- [八、LeetCode 实战练习](#八、LeetCode 实战练习)
- 总结
Rust 位运算详解
与十进制的算数运算一样,二进制的位运算也有其独特的运算规律。
参考资料:位运算 - 百度百科
一、与(AND)运算
运算符: &
1.1 Brian Kernighan 算法(布赖恩·克尼根算法)
利用与运算的一个经典技巧:n & (n - 1) 可以将 n 的二进制最右边的 1 置为 0。
应用:统计二进制数中 1 的个数
rust
fn count_ones(n: u64) -> u64 {
// n 为正整数,其二进制表示中 1 的个数
let mut n = n;
let mut count = 0;
while n != 0 {
n = n & (n - 1);
count += 1;
}
count
}
fn main() {
println!("{}", count_ones(15)); // 输出:4
}
算法解析: 每次执行
n = n & (n - 1)都会消去最低位的1,循环次数即为1的个数,时间复杂度为 O(k)(k 为 1 的个数)。
二、或(OR)运算
运算符: |
或运算规则:只要有一个操作数为 1,结果就为 1;两者都为 0 时,结果才为 0。
| A | B | 结果 |
|---|---|---|
| 0 | 0 | 0 |
| 0 | 1 | 1 |
| 1 | 0 | 1 |
| 1 | 1 | 1 |
三、非(NOT)运算
运算符: ~ 或 !
非运算对每一位取反:0 变 1,1 变 0。
四、异或(XOR)运算
运算符: ^
参考资料:
4.1 运算规则
| A | B | 结果 |
|---|---|---|
| 0 | 0 | 0 |
| 0 | 1 | 1 |
| 1 | 0 | 1 |
| 1 | 1 | 0 |
4.2 运算法则
| 法则 | 表达式 | 说明 |
|---|---|---|
| 归零律 | a ⊕ a = 0 | 任何数异或其本身都等于 0 |
| 恒等律 | a ⊕ 0 = a | 任何数异或 0 都等于其本身 |
| 交换律 | a ⊕ b = b ⊕ a | 交换操作数不影响结果 |
| 结合律 | a ⊕ b ⊕ c = a ⊕ (b ⊕ c) | 运算顺序不影响结果 |
| 自反性 | a ⊕ b ⊕ a = b | 与同一个数异或两次等于原数 |
| 可推导性 | d = a ⊕ b ⊕ c ⇒ a = d ⊕ b ⊕ c | --- |
示例:
- 若
x = 0101(二进制),y = 1011(二进制),则x ⊕ y = 1110 - 对任意整数
i,有4i ⊕ (4i+1) ⊕ (4i+2) ⊕ (4i+3) = 0
五、左移(SHL,Shift Left)运算
运算符: <<
用途: 快速乘 2,比算术乘法(*)速度更快。
rust
fn main() {
let x = 5;
let y = x << 1; // 相当于 x * 2
println!("{}", y); // 输出:10
}
原理: 二进制数左移一位,末位补 0,相当于乘以 2。
六、右移(SHR,Shift Right)运算
运算符: >>
用途: 快速除 2,比算术除法(/)速度更快。
rust
fn main() {
// 偶数右移
let mut x = 1024;
let mut y = x >> 1;
println!("{}", y); // 输出:512
// 奇数右移(小数部分截断)
x = 11;
y = x >> 1;
println!("{}", y); // 输出:5
}
注意: 奇数右移会丢弃最低位(小数部分截断),例如
11 >> 1 = 5(而非 5.5)。
七、Rust 中的位运算 Trait
Rust 标准库为位运算提供了对应的 trait,可用于自定义类型的运算符重载:
| Trait | 运算符 | 说明 |
|---|---|---|
| std::ops::BitAnd | & |
按位与运算符 |
| std::ops::BitAndAssign | &= |
按位与赋值运算符 |
| std::ops::BitOr | ` | ` |
| std::ops::BitOrAssign | ` | =` |
| std::ops::BitXor | ^ |
按位异或运算符 |
| std::ops::Not | ! |
按位非运算符 |
参考文档:BitAnd · BitAndAssign · BitOr · BitOrAssign · BitXor · Not
八、LeetCode 实战练习
位运算在算法题中有广泛应用,以下是推荐的练习题:
| 题目 | 主要考点 |
|---|---|
| 136. 只出现一次的数字 | 异或消除重复数 |
| 137. 只出现一次的数字 II | 位统计 |
| 191. 位 1 的个数 | Brian Kernighan 算法 |
| 201. 数字范围按位与 | 公共前缀 |
| 231. 2 的幂 | n & (n-1) == 0 |
| 260. 只出现一次的数字 III | 分组异或(同剑指 Offer 56-I) |
| 338. 比特位计数 | 动态规划 + 位运算 |
| 461. 汉明距离 | 异或 + 1 的个数 |
总结
| 运算 | 符号 | 典型用途 |
|---|---|---|
| 与 AND | & |
清除位、掩码、判断奇偶 |
| 或 OR | ` | ` |
| 非 NOT | ! / ~ |
取反 |
| 异或 XOR | ^ |
消除重复、交换两数、校验 |
| 左移 SHL | << |
快速乘 2 的幂次 |
| 右移 SHR | >> |
快速除 2 的幂次 |
提示: 位运算直接操作底层二进制,执行效率极高,在性能敏感场景和算法竞赛中被广泛使用。
本文为《Rust 编程》系列教程第十七章,持续更新中。