【问题标题】:java arithmeticjava算术
【发布时间】:2010-10-09 16:25:54
【问题描述】:

为什么这段代码返回错误的值?

int i=Integer.MAX_VALUE+1;
long l=Integer.MAX_VALUE+1;
System.out.println(l);
System.out.println(i);

【问题讨论】:

  • 字节 b1=100; //字节 b2=200; // 可能丢失精度字节 b3=100+1; //字节b4=127+1; // 可能的精度损失 int i1=2000000000; //int i2=2999999999; //整数太大:2999999999 int i3=2000000000+1; int i4=2147483647+1;现在我不明白为什么会出现不同类型的错误。对于 b4 变量 - 有错误,对于 i4 - 没有错误。

标签: java math integer-overflow


【解决方案1】:

当您将 1 添加到 Integer.MAX_VALUE 时,它会溢出并环绕到 Integer.MIN_VALUE

这是因为 Java 使用 two's complement 来表示整数。 4位示例:

0000 : 0
0001 : 1
...
0111 : 7 (max value)
1000 : -8 (min value)
...
1110 : -2
1111 : -1

因此,当您将 1 加到 0111(最大值)时,它会变为 1000,这是最小值。将此想法扩展到 32 位,它的工作方式相同。


至于为什么你的long 也显示不正确的结果,那是因为它在int s 上执行加法,然后 隐式转换为long。你需要做的:

long l = (long) Integer.MAX_VALUE + 1
System.out.println(l); // now prints the correct value

【讨论】:

  • 请告诉我是否看懂了解析这段代码虚拟机的算法:long l = Integer.MAX_VALUE +1; 1. long l - 我说虚拟机为这个变量分配64位内存。 2. Integer.MAX_VALUE +1——在这一行的虚拟机对变量l一无所知。这里是一个简单的算术运算,其结果——整数溢出。 3. 在 64 位(l 变量)的内存区域中,从第 2 行写入表达式结果 - 32 位不正确的值。我看到我们在第一步和第二步之间没有逻辑联系?是真的吗?
【解决方案2】:

顾名思义,Integer.MAX_VALUEInteger 可用的最大值。在 java 中,当 Integer 超过其最大值 1(或溢出 1)时,其值为 Integer.MIN_VALUE

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

注意,使用 Float 或 Double 时不会出现这种溢出,值为 POSITIVE_INFINITY

上溢的运算产生有符号无穷大,下溢的运算产生非规格化值或有符号零,而数学上没有明确结果的运算产生 NaN。


资源:

【讨论】:

    【解决方案3】:

    你试图存储一个不能用这种类型表示的值 (2^31 - 1),从而使 32 位整数类型溢出:

    int i = Integer.MAX_VALUE + 1;
    

    【讨论】:

      【解决方案4】:

      Java 整数是 32 位有符号类型,范围从:-2,147,483,648 到 2,147,483,647。

      您不能像在i=Integer.MAX_VALUE+1; 中那样设置i 整数变量

      【讨论】:

      • 以及在这种情况下会发生什么:long l=Integer.MAX_VALUE+1;现在 l 是 64 位。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-04-06
      • 2020-01-15
      • 1970-01-01
      • 2016-06-01
      相关资源
      最近更新 更多