20

我明天有一个测试,我无法理解我的书籍解释,我感谢帮助:

public class TestClass{
      public static void main(String[] args) throws Exception{
            int a = Integer.MIN_VALUE;
            int b = -a;
            System.out.println( a+ "   "+b);
      }
}

输出:-2147483648 -2147483648

为什么这会打印 2 个相同大小的负数而不是正数和负数?

4

4 回答 4

40

因为静默整数溢出:Integer.MIN_VALUEis-2^31Integer.MAX_VALUEis 2^31-1,所以-Integer.MIN_VALUEis 2^31, which is Integer.MAX_VALUE + 1,根据定义对于整数来说太大了。所以它溢出并变成Integer.MIN_VALUE......

您还可以检查:

System.out.println(Integer.MAX_VALUE + 1);

打印同样的东西。

从技术上讲,结果由Java 语言规范 #15.18.2 定义

如果整数加法溢出,则结果是数学和的低位,以一些足够大的二进制补码格式表示。如果发生溢出,则结果的符号与两个操作数值的数学和的符号不同。

于 2012-09-21T17:15:37.980 回答
5

基本上,因为Integer.MAX_VALUE实际上只有 2147483647,所以-Integer.MIN_VALUE,即 +2147483648,实际上溢出了整数内部二进制表示的容量。因此,结果“循环”回到Integer.MIN_VALUE或 -2147483648。

如果你这样做long b = -((long)a);了,你会得到预期的结果。

于 2012-09-21T17:18:52.687 回答
1

为了更清楚地表明这一点:

Integer.MIN_VALUE is -2^31 = -2147483648
Integer.MAX_VALUE is 2^31-1 = 2147483647 
/*notice this is 1 less than the negative value above*/

Integer.MAX_VALUE不能拿2147483648。对于整数来说,这个数字太大了,正好相差 1。这会导致数字从最大值返回到最小值的起始位置。

于 2013-10-10T20:54:25.093 回答
0

固定数量的二进制位可以编码偶数个事物。这意味着你不能有一个完全以零为中心的序列,因为这需要一个对称的事物数量。在句子中间最接近零的方法是将其拆分为负数和非负数,或正数和非正数。正常的二进制补码编码是前者。所以 32 位的范围从 -2^31 到 2^31-1。零在序列的非负半部分,并且您有一个无法正确否定的负数。

于 2020-07-17T05:11:59.910 回答