第十七 位运算

目录

  • [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 编程》系列教程第十七章,持续更新中。

相关推荐
TDengine (老段)18 小时前
TDengine Go 与 Rust 连接器 — 高性能异步访问
大数据·数据库·物联网·golang·rust·时序数据库·tdengine
魔力女仆21 小时前
【RUST AI】把 TTS 搬进浏览器:kokoroi-rs 的 WASM 实践
人工智能·rust·wasm
米尔的可达鸭1 天前
UDP 通信深度实验:从 Windows FastPath 到 ICMP 端口不可达的完整排查
windows·websocket·网络协议·rust·udp·wireshark·tcpdump
jinshw1 天前
自己实现GIS配图软件(二)
前端·后端·rust
行走的陀螺仪1 天前
从 nvm 到 fnm:更快、更省心的 Node.js 版本管理器迁移指南
rust·node.js·nvm·fnm
逻极2 天前
Rust 从入门到精通:内存安全与高性能系统编程实战
rust·系统编程·性能·内存安全
Yeauty2 天前
渲染成图再 CLI 拼接,还是进程内直推?Rust 帧到视频的两条路
开发语言·rust·音视频
向夏威夷 梦断明暄2 天前
从 Bun 的 Rust 重写,看 C# 如何重建 AI 基础设施层
人工智能·rust·c#
Ivanqhz2 天前
Rust collect() 浅析
开发语言·后端·rust
Ivanqhz3 天前
Rust &‘static str浅析
java·前端·javascript·rust