整型类型出现意外输出

5

学习JAVA时,我试图测试使用while循环来增加一个int的上限。请参见下面的程序:

 public class Test {

   public static int a(){
     int a = 10;
      while(a > 9 )
          ++a;
      return a; 
   }

   public static void main(String[] argc) {

         Test t = new Test();
         int k = t.a();
         System.out.println("k = "+(1 * k));    
    }
}

我知道32位范围是从-2,147,483,648到2,147,483,647,所以基于此,我期望的输出结果是2,147,483,647,但实际上我得到的是:

k = -2147483648

我甚至尝试了

 System.out.println("k = "+(1 * k/2)); 

但是输出仍然是:
k = -1073741824

问题:

为什么解决方案是负数而不是正数?

4个回答

5
你正在将 a 这个 int 值逐一加上 1,直到它达到了 1 + Integer.MAX_VALUE,这会使其值变为 -2147483648 == Integer.MIN_VALUE
下面是有注释的循环代码:
// "infinite" loop as a is assigned value 10
while(a > 9)
    // when a reaches Integer.MAX_VALUE, it is still incremented by 1
    ++a;
// loop condition now false, as value for a has shifted to -2147483648
return a; 

1
问题:那么当我们越过 Integer.MAX_VALUE 时,我们会自动转移到 Integer.MIN_VALUE ... 反之是否也成立? - NoobEditor
2
@NoobEditor 是的。由于没有明确的溢出或下溢错误,因此 Integer.MIN_VALUE - 1 == Integer.MAX_VALUE - Mena
我希望我2年前就知道这个!我当时很困惑。感谢您清晰的回答,点赞+1。 - RossC

2
正在发生的情况被称为整数溢出
32位整数的最大值(二进制)为: 0111 1111 1111 1111 1111 1111 1111 1111 当你给这个数字加1时,得到的结果是: 1000 0000 0000 0000 0000 0000 0000 0000 这是二进制补码,即-2,147,483,648。由于任何负数都小于9,所以while循环退出。

1

如果我们查看Oracle有关int值的文档,我们可以发现:

作用于int原始值的运算符不会指示溢出或下溢

结果由语言指定,并且与JVM版本无关,如下所示:

Integer.MAX_VALUE + 1 等同于 Integer.MIN_VALUE
Integer.MIN_VALUE - 1 等同于 Integer.MAX_VALUE


1
您需要将该值增加,直到它达到正限制并且所有位都变为1,但符号位不变。

0x7FFFFFFF = 01111111 11111111 11111111 11111111

这是数字2147483647的二进制表示,也就是INT_MAX。当您再次将其增加一时,它变成

0x80000000 = 10000000 00000000 00000000 00000000

这等于INT_MIN,即-2147483648。
现在,
2147483647大于9,因此您的循环继续。再增加一次,糟糕了,突然变成了-2147483648,比9小。这是循环条件失败的时候。

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