第十七 位运算

目录

  • [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)运算

运算符: ~!

非运算对每一位取反:0110

四、异或(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 编程》系列教程第十七章,持续更新中。

相关推荐
a诠释淡然1 天前
C++ vs Rust:哪个更适合你的下一个项目?
开发语言·c++·rust
Vallelonga1 天前
Rust 生命周期标注积累
开发语言·rust
星栈1 天前
Makepad UI 代码怎么读:别被语法吓住
前端·rust
MageGojo1 天前
基于 Rust + Headless Chrome 的自动化文章发布系统设计与登录态持久化实现
自动化测试·rust·桌面应用·headless-chrome·gpui
特立独行的猫a1 天前
Tauri Demo 移植到鸿蒙PC上的交叉编译全流程实战总结
华为·rust·harmonyos·tauri·鸿蒙pc
星栈独行1 天前
10 分钟跑起第一个 Makepad 应用:先把窗口开起来
前端·程序人生·ui·rust·开源·github
古城小栈1 天前
langchainrust:构建一个高效智能体
ai·rust
Yuyubow2 天前
gpui step by step 3. 消息传递 EventEmitter
rust
不爱学英文的码字机器2 天前
[鸿蒙PC命令行移植适配]移植rust三方库tokei到鸿蒙PC的完整实践
华为·rust·harmonyos