为什么此代码会打印两个负数?

avi*_*iad 15 java

int a = Integer.MIN_VALUE;
int b = -a;
System.out.println("a = "+a + " | b = "+b);
Run Code Online (Sandbox Code Playgroud)

结果:

a = -2147483648 | b = -2147483648

我期待b是一个正数.

And*_*res 20

改变符号Integer.MIN_VALUE会产生溢出; 你看到了结果.


Swe*_*per 16

如果你曾经做过这样的事情:

int a = Integer.MAX_VALUE;
a++;
System.out.println(a);
Run Code Online (Sandbox Code Playgroud)

您将知道当某些内容超出数据类型的最大值时,它会循环回到其最小值.当它小于最小值时,它会循环回到最大值.

这里发生了同样的事情.

否定int的最小值将在数学上给出2147483648,但因为这比最大值大1.它再次循环回最小值,即-2147483648.

有趣的事实:否定基本上是将每一位从0切换为1,将1切换为0,然后再加1.尝试这样做10000000000000000000000000000000这是int的min值在二进制中的样子.


Tez*_*zra 5

对于底层二进制解释,这是因为带符号的整数存储有二进制补码.

因此,二进制中最负的数字是1000 0000.为了反转符号,你翻转所有的位,然后添加一个...

1000 0000 => 0111 1111 + 1 = 1000 0000

你回到了起步的地方!

如上例所示,字节的有符号范围(8位)为-128到127,因此 - ( - 128)为128,超过127时为1,因此溢出回-128.

至于为何使用Two的补码?1 - 1变为1 +( - 1)或0001 + 1111 = 0000.因此,通过将负数存储在二进制补码中,通过仅取第二个数的二进制补码并将它们加在一起来完成减法.(这对于机器而言比向算术逻辑单元(ALU)添加减法电路要高效得多;因为它已经有了逐位补充而不是添加二进制补码).