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

时间:2017-05-15 16:54:15

标签: java

int a = Integer.MIN_VALUE;
int b = -a;
System.out.println("a = "+a + " | b = "+b);

结果:

  

a = -2147483648 | b = -2147483648

我原以为b是一个正数。

4 个答案:

答案 0 :(得分:21)

更改$('ul').append('[markup]') $('ul').listview('refresh'); 的符号会产生溢出;你看到了结果。

答案 1 :(得分:17)

如果您曾经做过类似的事情:

int a = Integer.MAX_VALUE;
a++;
System.out.println(a);

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

同样的事情发生在这里。

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

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

答案 2 :(得分:5)

对于基础二进制解释,这是因为带符号的整数与Two's complement一起存储。

所以,二进制中最负数是1000 0000.要反转符号,你要翻转所有位,然后加一个......

1000 0000 => 0111 1111 + 1 = 1000 0000

你回到了开始的地方!

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

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

答案 3 :(得分:1)

通常当我们尝试为一个大于int类型的最大值的int类型赋值时,它的loopbacks再次从int的min值开始,例如

2147483648 -will become-> -2147483648
2147483649 -will become-> -2147483647
2147483650 -will become-> -2147483646

a的第一个语句值为-2147483648

当你做int b = -a;时,b通常应该

b = -a --> -(-2147483648) --> 2147483648

但int的最大正值为214748364721474836482147483647大一个,它将循环回1并变为-2147483648