我理解Java中的(2 * i ==(i ^(i - 1)+ 1)会让我发现一个数字是2的幂。但有人可以解释为什么这有效吗?
答案 0 :(得分:14)
2 * i ==(i ^(i-1))+ 1
基本上,如果i
是2的幂,它的位模式将只有一个1
。如果从中减去1,则1
位的所有低位变为1
,并且该2位幂将变为0.然后对位执行XOR
,产生全1位模式。你加1,你得到下一个2的幂。
记住异或真值表:
1 ^ 1 = 0
1 ^ 0 = 1
0 ^ 1 = 1
0 ^ 0 = 0
示例:
假设i
为256,这就是这种位模式。
100000000 = 2^8 = 256
100000000 - 1 = 011111111 = 2^7 + 2^6 + ... + 2^0 = 255
100000000 ^ 011111111 = 111111111 = = 2^8 + 2^7 + ... + 2^0 = 511
111111111 + 1 = 1000000000 = 2^9 = 512 = 2*i
以下是您未获得2
功能的示例i = 100 = 2^6 + 2^5 + 2^2
0110 0100
0110 0100 - 1 = 99 = 2^6 + 2^5 + 2^1 + 2^0 = 0110 0011
0110 0100 ^ 0110 0011 = 0000 0111 = 2^2 + 2^1 + 2^0 = 7
0000 0111 + 1 = 000 1000 = 2^3 = 8 != (2*i)
简化版
此外,还有一个此检查的修改版本,用于确定某个正无符号整数是否为2的幂。
(i & (i-1)) == 0
基本上,相同的理由
如果i
是2的幂,则其位表示中只有一个1
位。如果从中减去1,则1
位变为0,所有低位变为1
。然后AND
将产生全0
位模式。
答案 1 :(得分:0)
重要的一点是i ^(i-1)(我假设这是问题中的一个小错字)。假设i是2的幂。那么它的二进制扩展是1,后跟很多零。 i-1是一个数字,其中前导1被零替换,所有的零被1替换。因此,XOR的结果是1的字符串,与i的位数相同。
另一方面,如果i不是2的幂,则从中减去1将不会翻转所有这些位 - 然后xor会在您减去时识别哪些位从一个位置传送到下一个位置1. xor的结果将为零,因此当您添加1时,它将不会进入下一位位置。