为什么在一种情况下乘以大数会给出错误的结果?

mac*_*rre 2 java int primitive multiplication

这可能看起来很简单,但我没有任何答案。当我写:

 System.out.println (100 * 1000 * 10000 * 100000);
 System.out.println (100 * 1000 * 10000 * 100000.0);
Run Code Online (Sandbox Code Playgroud)

它返回这些值:

276447232
1.0E14
Run Code Online (Sandbox Code Playgroud)

我知道这与某些数据类型的最大值有关。但我只想明确回答为什么它为两个方程返回这些确切值。如果有人可以向我解释这一点,我将不胜感激。

第一个返回值与 int 数据类型的最大值不匹配,这就是我感到困惑的原因。我假设的第二个返回值是双精度值或浮点值,但我不确定。

Ort*_*kni 6

在表达式中

System.out.println (100 * 1000 * 10000 * 100000);
Run Code Online (Sandbox Code Playgroud)

参数是 anint并且结果超过了 an 允许的最大值int,即2147483647。这就是我们所说的溢出。根据Java 语言规范

如果整数乘法溢出,则结果是数学乘积的低位,以某种足够大的二进制补码格式表示。

取一个数的 N 个低位相当于计算这个数除以 2^N 的余数。在我们的例子中,N=32 因为int存储在 32 位上。这就是为什么 Jon Skeet 回答说

100000000000000 % (2^32) 是 276447232。

在表达式中

System.out.println (100 * 1000 * 10000 * 100000.0);
Run Code Online (Sandbox Code Playgroud)

三个第一因子的乘积100 * 1000 * 10000给出1_000_000_000小于最大值int。最后的乘法导致二进制数字提升,这意味着,在这种情况下,它1_000_000_000被转换(提升)为double,然后乘以100000.0