long m = 24 * 60 * 60 * 1000 * 1000;
上面的代码会产生溢出,并且不会打印正确的结果。
long m2 = 24L * 60 * 60 * 1000 * 1000;
long m3 = 24 * 60 * 60 * 1000 * 1000L;
以上两行打印正确的结果。
我的问题是 -
m2
或m3
?答案 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
。最后,使用m2
和m3
完成了分配。
是的,乘法从左到右的相关性 - 意味着左操作数先被占用。基于这个事实,我认为在这种情况下我们应该使用 -
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 * long
和long * int
生成long
)。
在这种情况下,您可以像开始m2
:24L * 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中的表达式从左到右计算。