求问判断2的幂的算法原理:n && !(n & (n - 1))如何工作?
理解判断2的幂的巧妙算法
嘿,这个用来判断数是否为2的幂的小算法确实挺精妙的,我来一步步给你拆解它的运行逻辑:
核心前提:2的幂的二进制特征
所有正整数的2的幂(比如2、4、8、16...),它们的二进制表示都有一个共同特点:只有一个二进制位是1,其余全是0。举几个例子:
- 2 →
10 - 4 →
100 - 8 →
1000 - 16 →
10000
关键操作:n & (n - 1)的作用
当我们把一个2的幂的数n减1时,会发生什么?比如:
- 4-1=3 → 二进制
011(原来的唯一1变成0,后面的0全变成1) - 8-1=7 → 二进制
0111
这时候对n和n-1做**按位与(&)**操作,因为两个数的二进制位没有任何一位同时为1,结果必然是0。比如:
4 & 3→100 & 011 = 000(即数值0)8 &7→1000 & 0111 = 0000(即数值0)
反过来,如果n不是2的幂,那它的二进制里至少有两个1。比如6(110),n-1=5(101),按位与的结果是100(数值4),显然不是0;再比如9(1001),n-1=8(1000),按位与结果是1000(数值8),也不是0。所以n & (n-1) === 0是n为2的幂的必要条件。
为什么要加n &&?
这是为了处理边界情况:当n=0时,0 & (-1)(二进制全1)的结果也是0,但0并不是2的幂。n &&的作用是先确保n是一个非0的数(在JS里,非0数值会被当作true,0会被当作false),这样就能把0排除在外。同时,这个判断也能排除负数(负数的二进制按位与逻辑不符合2的幂的规则)。
结合你的代码看运行效果
你的循环代码从2遍历到16,调用potence(i)判断:
var potence = n => n && !(n & (n - 1)); for(var i = 2; i <= 16; ++i) { if(potence(i)) console.log(i + " is potence of 2"); }
运行后会输出:
2 is potence of 2 4 is potence of 2 8 is potence of 2 16 is potence of 2
完全符合预期,因为这些数都是2的幂。
内容的提问来源于stack exchange,提问作者J. Uchu
相关产品推荐
相关产品推荐

