只有模数是2的整数次幂(如2、4、8、16、1024)时,才能用位运算x & (n-1)安全替代x % n,因其二进制低位掩码特性保证结果等价。

什么时候能用位运算替代 %?
只有模数是 2 的整数次幂(比如 2、4、8、16、1024)时,才能安全用位运算替代 %。因为 n % (1 等价于 <code>n & ((1 ,本质是取低 <code>k 位。一旦模数不是 2 的幂(如 7、10、100),位运算就无法直接等价替换,硬套会得到错误结果。
n & (mod - 1) 的正确写法和边界条件
假设你要算 n % 8,可写成 n & 7(因为 8 - 1 == 7,二进制是 111)。但必须注意:
-
n必须是非负整数;对负数,%返回负余数(C++ 标准行为),而&总是返回非负值,结果不一致 -
mod必须是 2 的幂且大于 0,否则mod - 1无意义或产生全 1 掩码(如mod == 0会崩溃) - 编译器通常能自动对常量模数做此优化(如
n % 16→n & 15),手动写位运算仅在模数非常数或需明确控制时才有必要
实际代码中怎么写才不容易出错?
推荐封装成带检查的宏或 constexpr 函数,避免手误。例如:
constexpr int fast_mod(int n, int mod) {
if (mod <= 0 || (mod & (mod - 1)) != 0)
return n % mod; // 回退到普通取模
return n & (mod - 1);
}这里 (mod & (mod - 1)) == 0 是判断 mod 是否为 2 的幂的经典技巧(对正整数成立)。但要注意:
立即学习“C++免费学习笔记(深入)”;
- 该判断对
mod == 1成立(1是2^0),n & 0结果恒为0,符合n % 1 == 0 - 不能用于浮点或大整数(如
uint64_t需用对应位宽的掩码) - 如果
n来自用户输入或可能为负,务必先做非负处理(如(n % mod + mod) % mod),位运算本身不解决符号问题
性能真的快吗?现代 CPU 下还值得优化吗?
单次操作上,& 比 % 快一个数量级(后者通常是多周期指令),但在多数场景下,差异微乎其微。真正影响性能的是:
- 是否在热点循环里频繁调用(比如哈希表寻址、环形缓冲区索引)
- 编译器是否已帮你优化:Clang/GCC 在
-O2及以上对常量模数基本都会自动转成位运算 - 可读性代价:写
n & 15不如写n % 16直观,维护时容易误解意图
所以,除非 profiler 明确指出 % 是瓶颈,且模数确定为 2 的幂、n 恒非负,否则优先写 % —— 更安全、更易懂。位运算是手段,不是目的。


















