乘法发生溢出

时间:2015-06-02 20:52:14

标签: java multiplication integer-overflow

long m = 24 * 60 * 60 * 1000 * 1000;

上面的代码会产生溢出,并且不会打印正确的结果。

long m2 = 24L * 60 * 60 * 1000 * 1000;
long m3 = 24 * 60 * 60 * 1000 * 1000L;

以上两行打印正确的结果。

我的问题是 -

  1. 我使用的编译器,m2m3
  2. 是否重要
  3. java如何开始倍增?从左到右还是从右到左? 24 * 60是先计算还是1000 * 1000?

6 个答案:

答案 0 :(得分:19)

在这种情况下 -

long m = 24 * 60 * 60 * 1000 * 1000;  

首先评估作业的权利。右侧没有long类型数据。全部都是int。因此JVM尝试将结果拟合到int,然后发生溢出。

在第二种情况下 -

long m2 = 24L * 60 * 60 * 1000 * 1000;
long m3 = 24 * 60 * 60 * 1000 * 1000L;

这里乘法的一个操作数是long。因此,其他会自动提示long。结果是试图适合long。最后,使用m2m3完成了分配。

是的,乘法从左到右的相关性 - 意味着左操作数先被占用。基于这个事实,我认为在这种情况下我们应该使用 -

long m2 = 24L * 60 * 60 * 1000 * 1000;  

这句话,因为在这个声明中,促进long之前提到的地方减少了溢出的风险。

答案 1 :(得分:16)

我会使用m2行代替m3行。

Java从left to right计算乘法运算符*,因此首先计算24 * 60

恰好24 * 60 * 60 * 1000(一个1000)没有溢出,所以当你乘以1000L时(第二个1000) ,产品在乘以之前会升级为long,因此不会发生溢出。

但正如您在评论中提到的,在将int数字乘以最后long数字之前,更多因素可能导致long数据类型溢出,从而产生错误答案。最好使用m2字面值作为long中的第一个(最左侧)数字,以避免从一开始就溢出。或者,您可以将第一个文字投射为(long) 24 * 60 * ...,例如byte[]

答案 2 :(得分:9)

Since expressions are evaluated from left to right,我更喜欢您的第一个解决方案(m2 = ...)。

推理:让我们看一个稍微不同的例子。

long g = Integer.MAX_VALUE * 2 * 2L;

此表达式将计算为-4,因为只有最后一次乘法将第一个表达式转换为long(此时为-2,因为两个操作数均为{{1} })。如果你写

int

相反,long g = Integer.MAX_VALUE * 2L * 2; 将保持预期值g,因为第一次乘法会产生8589934588类型的结果。

答案 3 :(得分:6)

乘法从左到右,int * int生成int。所以

24 * 60 * 60 * 1000 * 1000

相同
(((24 * 60)* 60) * 1000) * 1000

给了我们

(((1440)* 60) * 1000) * 1000
((  86400   ) * 1000) * 1000
(    86400000       ) * 1000

最后因为整数溢出(因为86400000000对于整数而言太大而最大值为2147483647)结果将是

500654080

您可以使用long作为参数之一消除整数溢出(int * longlong * int生成long)。

在这种情况下,您可以像开始m224L * 60那样在开始时执行此操作,这将产生long 1440L,它将再次乘以{{ {1}}生成新的60,依此类推,只生成long个值。

long案例在此处有效,因为您将m3乘以86400000,这意味着您避免整数溢出,因为结果将为1000L

答案 4 :(得分:4)

让我们乘以更多数字,即使有 # Unshare the mask if necessary to avoid propagation if not self._isfield: self.unshare_mask() _mask = ndarray.__getattribute__(self, '_mask') ,此行也会溢出:

1000L

虽然这会得到正确的结果:

long m3 = 24 * 60 * 60 * 1000 * 1000 *  1000 * 1000L;

所以我们确定java从左到右开始相乘,我们必须从左边开始long m3 = 24L * 60 * 60 * 1000 * 1000 * 1000 * 1000; 以防止溢出。

答案 5 :(得分:2)

这是因为当我们使用long作为一个操作数时,另一个clusterer.setInitializationMethod(new SelectedTag); 类型的操作数会被提示int

java中的表达式从左到右计算。