为什么 Integer.MIN_VALUE 的相反数等于它本身?

11

考虑下面的Java代码。

Integer value = Integer.MIN_VALUE;
System.out.println(value);

value = -value;
System.out.println(value);

输出

-2147483648
-2147483648

Integer.MIN_VALUE的负值为什么还是它本身?但结果不能是2147483648,因为Java中Integer的最大值是2147483647

想知道为什么是-2147483648?内部发生了哪种位运算操作?


对于重新开放投票者,重复中的此答案解释了Integer.MIN_VALUE的否定。 重复不是关于问题是否相同,而是关于“此问题已经有答案在这里”,正如标签所述。 - Sotirios Delimanolis
2个回答

16
当你对-2147483648取反时,它会变成2147483648,超过了Integer.MAX_VALUE的值,加上1后这个值会溢出并重新变成Integer.MIN_VALUE
根据JLS

整型包括byte、short、int和long,它们的值是8位、16位、32位和64位的有符号二进制补码整数。

因此,对整数进行的每个一元运算实际上都会应用于该数字的二进制补码表示。当达到Integer.MAX_VALUE时,它将由一个前导的0和31个1位组成。加上1 将使它成为一个前导的1和31个尾随的0的数字,这实际上是Integer.MIN_VALUE的二进制补码表示。

2
当达到Integer.MAX_VALUE时,它将由32个1位组成。加1会使其成为一个33位数,其中有一个前导的1和尾随的0位。- 你理解错了一点。Integer.MAX_VALUE是一个0后面跟着31个1位。将其加一得到的结果是1后面跟着31个0位,这是Integer.MIN_VALUE的二进制补码表示形式。 - Eran

14

内部进行了哪些位运算操作?

Java使用有符号数的二进制补码表示法(two's complement)。因此,改变符号的操作分为两步:

  1. 按位取反原始值,然后
  2. 将结果加上 1

2147483648 的表示如下:

10000000000000000000000000000000

反转它会产生

01111111111111111111111111111111

加上1后,它变成同一个数字,即

10000000000000000000000000000000

由于整数溢出。


1
为什么您将输入限制为正数? - laune
@Codebender,1的加法结果大于int类型可以容纳的最大正值,因此发生了溢出。 - Sergey Kalinichenko
另一个小问题:从技术上讲,在n位加法器中,将1添加到011...1不会导致溢出,即在这种情况下,进位标志不会被设置。只有将第一位解释为符号位才会产生“环绕”效果。 - laune
@laune 这是一种溢出,因为溢出或“V”标志将被设置为结果。 - Sergey Kalinichenko
我认为检查溢出标志是 Math.negateExact(int) 内在化的方式。 - the8472
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接