Ste*_*sop 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.
Run Code Online (Sandbox Code Playgroud)


Mik*_*uel 48

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

((n & -n) == n) 当n是2的幂,或2的幂的负,或零.

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

 n      0000100...000
-n      1111100...000
 n & -n 0000100...000
Run Code Online (Sandbox Code Playgroud)

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

n          0000100...000
inverse n  1111011...111
                     + 1
two's comp 1111100...000
Run Code Online (Sandbox Code Playgroud)

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

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

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

  • @Michael,我们可以对'n`的类型设置很好的界限,因为这个问题有"java"标签.`&`没有在Java中的`double`或`float`上定义.它仅在整数类型和布尔值上定义.由于`-`没有为布尔定义,我们可以安全地推断`n`是不可变的. (3认同)
  • 对于`(0&-0)== 0`,[紧接在前的语句](http://developer.classpath.org/doc/java/util/Random-source.html#line.292)是`if (n <= 0)扔...`.这意味着被测数量在该点永远不会为0(或负数). (2认同)

Joh*_*ica 13

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

1 & 1 = 1
1 & 0 = 0
0 & 1 = 0
0 & 0 = 0
Run Code Online (Sandbox Code Playgroud)

所以只有当两个字段都是1时才会出现1.

现在-n做了2的补码.它将所有内容更改01并添加1.

7 = 00000111
-1 = NEG(7) + 1 = 11111000 + 1 = 11111001
Run Code Online (Sandbox Code Playgroud)

然而

8 = 00001000
-8 = 11110111 + 1 = 11111000 

00001000  (8)
11111000  (-8)
--------- &
00001000 = 8.
Run Code Online (Sandbox Code Playgroud)

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


Ecl*_*pse 8

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

base 2    base 10
000001 =  1 
000010 =  2
000100 =  4
     ...
Run Code Online (Sandbox Code Playgroud)

要获得二进制补码的负值,可以翻转所有位并添加一个.对于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
Run Code Online (Sandbox Code Playgroud)

您可以很容易地看到第2列和第4列的结果与第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
Run Code Online (Sandbox Code Playgroud)

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