1左移31(1 << 31)如何工作以获得最大int值?以下是我在网上发现的想法和一些解释

HM9*_*527 1 bit-manipulation max bit twos-complement

我对比特操纵相当新,我想弄清楚(1 << 31) - 1是如何工作的.

首先我知道1 << 31是

1000000000000000000000000000
Run Code Online (Sandbox Code Playgroud)

而且我知道它实际上是最小int值的补充,但当我试图找出(1 << 31) - 1时,我发现一个解释说明,它只是

10000000000000000000000000000000 - 1 = 01111111111111111111111111111111
Run Code Online (Sandbox Code Playgroud)

我几乎想要相信它,因为它真的很简单.但这真的发生了什么?如果不是,为什么它恰好是正确的?

我原来的想法是,真正的过程应该是:-1的两个补码是

11111111111111111111111111111111
Run Code Online (Sandbox Code Playgroud)

然后(1 << 31) - 1 =

(1)01111111111111111111111111111111
Run Code Online (Sandbox Code Playgroud)

最左边的1被放弃,然后我们有int的最大值.

我真的很困惑哪一个是对的.

Boa*_*ann 6

这两个都是!1 << 31是:

1000 0000 0000 0000 0000 0000 0000 0000
Run Code Online (Sandbox Code Playgroud)

减1给出:

0111 1111 1111 1111 1111 1111 1111 1111
Run Code Online (Sandbox Code Playgroud)

关于有符号数的二进制补码布局的一个很好的特性是加法和减法与无符号数的操作完全相同.因此10000 ... 000表示二进制补码中的负数,最大负数,在这种情况下为-2,147,483,648,从中减去1导致回绕到最大正数2,147,483,647,但是排列了两个补数这样我们就可以假装它是无符号数,所以减法并不复杂.从10000 ... 000减去1只是将前导1减少到0,并借用一堆1,与十进制相同,得到一堆9:10000 - 1 = 9999.

这也是事实,数学,(a - b)是一样的(a + (-b)),所以我们可以做(1 << 31) + (-1),而不是:

  1000 0000 0000 0000 0000 0000 0000 0000    (1 << 31)
  1111 1111 1111 1111 1111 1111 1111 1111    (-1)
-----------------------------------------
1 0111 1111 1111 1111 1111 1111 1111 1111    +

  0111 1111 1111 1111 1111 1111 1111 1111    (truncate)
Run Code Online (Sandbox Code Playgroud)

从高端执行1,并且一旦结果被截断回32位整数就丢失.

无论哪种方式,该模式,在高端使用单个0,然后填充1s,表示任何宽度的二进制补码整数的最大正值.

如果您愿意,还有其他方法可以生成该模式,例如~(1 << 31),和(-1 >>> 1)(其中>>>表示逻辑右移),这与整数宽度无关.