n & (n - 1) == 0 且 n > 0 能准确判断正整数是否为2的幂,因2的幂二进制仅一个1,n-1将其变为0并置后缀全1,与运算得0;需排除0和负数,推荐用 unsigned int 或先检查 n > 0。

为什么 n & (n - 1) 能判断 2 的幂?
因为 2 的幂在二进制下只有一个 1,比如 8 是 1000,16 是 10000。而 n - 1 会把那个唯一的 1 变成 0,后面所有位变成 1 —— 所以 n & (n - 1) 结果必为 0。
但要注意:0 不是 2 的幂,而 0 & (0 - 1) 在补码下是 0 & 0xFFFFFFFF(32 位),结果非零,所以必须先排除 0。
常见错误:直接写 (n & (n - 1)) == 0,没判 n > 0,导致 0、负数也被误判为真。
n > 0 和 n & (n - 1) == 0 必须同时成立
这是最简且安全的写法,兼顾正确性与性能。编译器对这种模式识别很好,通常生成单条 and 指令加分支判断。
-
n必须是无符号整型或已确认为正数;若n是有符号 int,负数参与位运算行为未定义(实际多数平台按补码算,但不可依赖) - 对
unsigned int、uint64_t等类型同样适用,无需改逻辑 - 不要用
log2(n)或循环除 2——慢,且浮点取整引入精度风险
边界情况:最小值和大数怎么处理?
INT_MIN(如 -2147483648)不是 2 的幂,但 n - 1 会溢出(有符号整型下未定义行为)。所以务必确保输入是正整数或使用无符号类型。
示例安全写法:
组合式C++代码评审方案,融合静态分析、AI推理、多轮迭代评审和C++专项检查,适用于PR审查、增量代码审查、全项目评审和代码质量评分,触发词包括review cpp、cpp代码评审、C++review、代码审查。
bool isPowerOfTwo(unsigned int n) {
return n != 0 && (n & (n - 1)) == 0;
}
如果接口只能接收 int,先做符号检查:
bool isPowerOfTwo(int n) {
return n > 0 && (n & (n - 1)) == 0;
}
注意:1 是 2^0,合法;INT_MAX(2147483647)不是 2 的幂,该逻辑能正确返回 false。
编译器优化和可移植性提醒
现代编译器(GCC/Clang/MSVC)都能将 n > 0 && (n & (n - 1)) == 0 优化为极简汇编,通常比查表或内置函数(如 __builtin_popcount)更快。
但别用 __builtin_clz 或 _BitScanForward —— 这些依赖具体架构或编译器,且要额外处理 0 输入,反而增加分支和复杂度。
真正容易被忽略的是:这个技巧只适用于「正整数」,任何想套用到浮点、大整数库(如 boost::multiprecision)或任意进制的场景,都得换思路。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!










