运算符 | 语法 | 功能 | 典型应用场景 |
---|---|---|---|
& |
a & b |
按位与 | 掩码操作、判断奇偶、权限检查 |
| |
a | b |
按位或 | 合并标志位、设置权限 |
^ |
a ^ b |
按位异或 | 交换变量、数据加密、去重 |
&^ |
a &^ b |
位清空(AND NOT) | 清除指定标志位 |
<< |
a << n |
左移 | 快速乘2ⁿ、位掩码生成 |
>> |
a >> n |
右移 | 快速除2ⁿ、提取高位数据 |
关键:
const (
Read = 1 << iota // 0b001 (1)
Write // 0b010 (2)
Execute // 0b100 (4)
)
// 添加权限:user |= Read | Write
// 检查权限:(user & Read) != 0
// 清除权限:user &^= Write
判断奇偶:n & 1 == 0 比 n % 2 == 0 快 3~5 倍
交换变量(无临时变量):
a ^= b
b ^= a
a ^= b
2 的幂判断:n & (n-1) == 0
只出现一次的数字(LeetCode 136):
func singleNumber(nums []int) int {
result := 0
for _, num := range nums {
result ^= num // 利用 a ^ a = 0 的性质
}
return result
}
type Bitmap struct {
bits []uint64
}
// 设置第 n 位为 1
func (b *Bitmap) Set(n int) {
index, offset := n/64, uint(n%64)
b.bits[index] |= 1 << offset
}
// 检查第 n 位
func (b *Bitmap) Get(n int) bool {
index, offset := n/64, uint(n%64)
return (b.bits[index] & (1 << offset)) != 0
}
海量数据去重、快速检索(10亿数据仅需 125MB 内存)
IP 地址转换:
ip := 0xC0A80101 // 192.168.1.1
part1 := byte(ip >> 24) // 192
part2 := byte(ip >> 16) // 168
❌ 错误写法:
if flags & Read != 0 { ... } // 等价于 flags & (Read != 0)
✅ 正确写法:
if (flags & Read) != 0 { ... } // 必须加括号!
var a uint8 = 255
b := a << 1 // 结果为 254(而非 510),uint8 溢出
移位长度不能超过类型位数(如 int32 最多移 31 位)
var a int8 = -8 // 二进制: 11111000
b := a >> 2 // 结果: -2 (11111110)
右移负数时高位补 1(符号位扩展)
操作 | 位运算实现 | 传统实现 | 性能提升 |
---|---|---|---|
乘 2 | n << 1 |
n * 2 |
3~5 倍 |
除 2(向下取整) | n >> 1 |
n / 2 |
2~4 倍 |
奇偶判断 | n & 1 |
n % 2 |
4~6 倍 |
取模 2 k 2^k 2k | n & (k-1) |
n % k |
10 倍+ |
⚠️ 注意:现代编译器可能自动优化简单算术,但位运算在复杂表达式和底层系统中仍具优势。
Q:x & (x-1) 有什么深层用途?
A:
判断是否为 2 的幂(结果为 0 则是)
计算二进制中 1 的个数(循环直到 0)
求最低位的 1(x & ^(x-1))
Q:如何用位运算实现加法?
A:
func add(a, b int) int {
for b != 0 {
carry := a & b // 计算进位
a = a ^ b // 无进位加法
b = carry << 1 // 进位左移
}
return a
}
题目:实现函数 func reverseBits(num uint32) uint32(翻转二进制位)
答案:
func reverseBits(num uint32) uint32 {
result := uint32(0)
for i := 0; i < 32; i++ {
// 取 num 的最低位,放到 result 的对应高位
result = (result << 1) | (num & 1)
num >>= 1
}
return result
}
注意点: