为什么如果(n& -n)== n那么n是2的幂?

时间:2011-09-13 16:44:36

标签: java logic bit-manipulation

Line 294 of java.util.Random source

if ((n & -n) == n) // i.e., n is a power of 2
    // rest of the code

为什么会这样?

7 个答案:

答案 0 :(得分:95)

因为在2的补码中,-n~n+1

如果n是2的幂,那么它只设置一个位。所以~n除了那个之外都设置了所有位。添加1,然后再次设置特殊位,确保n & (that thing)等于n

反过来也是如此,因为该Java源中的前一行排除了0和负数。如果n设置了多个位,那么其中一个位是最高位。这个位+1设置,因为有一个较低的清除位来“吸收”它:

 n: 00001001000
~n: 11110110111
-n: 11110111000  // the first 0 bit "absorbed" the +1
        ^
        |
        (n & -n) fails to equal n at this bit.

答案 1 :(得分:48)

描述并不完全准确,因为(0 & -0) == 0但0不是2的幂。更好的说法是

((n & -n) == n)当n是2的幂时,或2的幂的负数,或者为零。

如果n是2的幂,则二进制中的n是单个1,后跟零。 -in的二进制补码是反+ 1,所以这些位排成一行

 n      0000100...000
-n      1111100...000
 n & -n 0000100...000

要了解这项工作的原因,请将二进制补码视为反+ 1,-n == ~n + 1

n          0000100...000
inverse n  1111011...111
                     + 1
two's comp 1111100...000

因为你在添加一个以获得两个补码时一直带着它。

如果n不是2的幂†那么结果将会丢失一点,因为由于该进位,两个补码不会设置最高位。

† - 或零或2的幂的负数......如顶部所述。

答案 2 :(得分:13)

您需要将值视为位图,以了解为什么这是真的:

1 & 1 = 1
1 & 0 = 0
0 & 1 = 0
0 & 0 = 0

因此,只有当两个字段均为1时才会出现1。

现在-n做了2的补充。它会将0更改为1并添加1。

7 = 00000111
-1 = NEG(7) + 1 = 11111000 + 1 = 11111001

然而

8 = 00001000
-8 = 11110111 + 1 = 11111000 

00001000  (8)
11111000  (-8)
--------- &
00001000 = 8.

只有2的幂才(n & -n)为n 这是因为2的幂表示为零的长海中的单个设置位。 否定将产生完全相反的,在1的海洋中产生单个零(在曾经是1的地方)。添加1会将较低的一个移动到零所在的空间 按位和(&)将再次过滤掉。

答案 3 :(得分:8)

在二进制补码表示中,关于2的幂的独特之处在于它们由全0位组成,除了第k位,其中n = 2 ^ k:

base 2    base 10
000001 =  1 
000010 =  2
000100 =  4
     ...

要获得二进制补码的负值,请翻转所有位并添加一位。对于2的幂,这意味着你在左边得到一堆1,包括正值的1位,然后是右边的一堆0:

n   base 2  ~n      ~n+1 (-n)   n&-n  
1   000001  111110  111111      000001
2   000010  111101  111110      000010
4   000100  111011  111100      000100
8   001000  110111  111000      001000

您可以很容易地看到第2列和第2列的结果4将与第2列相同。

如果你看一下这个图表中缺少的其他值,你就可以看出为什么除了2的权力之外没有任何其他值:

n   base 2  ~n      ~n+1 (-n)   n&-n  
1   000001  111110  111111      000001
2   000010  111101  111110      000010
3   000011  111100  111101      000001
4   000100  111011  111100      000100
5   000101  111010  111011      000001
6   000110  111001  111010      000010
7   000111  111000  111001      000001
8   001000  110111  111000      001000

n& -n将(对于n> 0)仅设置1位,并且该位将是n中的最低有效位设置位。对于所有2的幂次数,最低有效设置位是唯一的设置位。对于所有其他数字,有多个位集,其中只有最低有效位将在结果中设置。

答案 4 :(得分:4)

它的权力为2及其two's complement

例如,取8:

8  = 0b00001000

-8 = 0b11111000

计算二者的补码:

Starting:  0b00001000
Flip bits: 0b11110111  (one's complement)
Add one:   0b11111000  

AND 8    : 0b00001000

对于2的幂,只有一位将被设置,因此添加将导致设置2 n 的n th 位(一个人继续携带到n th 位。然后当你AND这两个数字时,你会得到原来的数据。

对于非幂2的数字,其他位不会被翻转,因此AND不会产生原始数字。

答案 5 :(得分:4)

简单地说,如果n是2的幂,则意味着只有一位设置为1而其他位为0:

00000...00001 = 2 ^ 0
00000...00010 = 2 ^ 1
00000...00100 = 2 ^ 2
00000...01000 = 2 ^ 3
00000...10000 = 2 ^ 4

and so on ...

并因为-nn的2的补码(这意味着唯一的1位保持不变,并且该位左侧的位位于1,实际上不是没关系,因为如果两个位中的一个为零,AND运算符&的结果将为0):

000000...000010000...00000 <<< n
&
111111...111110000...00000 <<< -n
--------------------------
000000...000010000...00000 <<< n

答案 6 :(得分:0)

通过示例显示:

8 in hex = 0x000008

-8 in hex = 0xFFFFF8

8&amp; -8 = 0x000008