错误的乘法结果

12

我正在尝试理解为什么这个乘法结果不正确:

long max = (60 * 24 * 60 * 60 * 1000);

这应该等于5,184,000,000。

但在我的Java程序中,它等于889,032,704。

有任何想法为什么会这样吗?


请使用无符号长整型或长长整型。 - coder hacker
5
这个问题被标记为 Java,而 Java 不支持您推荐的类型。 - Michael
这个问题已经被问过多次了。它是一个或多个现有问题的副本。 - devnull
请参见https://dev59.com/t2cs5IYBdhLWcg3wjUqR。 - devnull
特别是这个答案 - devnull
2个回答

17

你正在进行乘法运算的所有值都是int类型,因此结果也是int类型的。在溢出发生之后将其转换为long类型。让其中一个因数成为long类型,以便使用64位指令进行乘法运算。

尝试一下。

long max = (60L * 24L * 60L * 60L * 1000L);

L后缀指定常量是long值,而不是int常量。

语言规范中说:

如果整数字面值以ASCII字母L或l(小写L)结尾,则其类型为long;否则为int类型(§4.2.1)。

乘法部分的说明如下:

乘法表达式的类型是其操作数的提升类型。

两个int类型变量的类型提升会将它们保留为int类型:

根据以下规则,应用扩展原始转换(§5.1.2)将一个或两个操作数转换为指定类型:

  • 如果任一操作数的类型是double,则另一个操作数转换为double
  • 否则,如果任一操作数的类型是float,则另一个操作数转换为float
  • 否则,如果任一操作数的类型是long,则另一个操作数转换为long
  • 否则,两个操作数都转换为int类型

谢谢Mike。你的解释非常清晰易懂。 - Kyle Anderson
1
@punkrocker27ka,这是一个常见的错误。如此常见,以至于Go民决定使整数常量具有任意精度:“数字常量表示任意精度的值,并且不会溢出。...这些要求适用于字面常量和计算常量表达式的结果。” - Mike Samuel
太棒了:),这个工作像魔法一样,解释得非常好:) - sameerali

5
这是由于整数溢出引起的。你的右侧乘积被表示为int(所有操作数的默认类型),显然无法容纳你的“long”值。
只需将产品的第一个因子设置为long,可以使用长常量60L,如Mike的答案中所示,或者显式转换为(long) 60 :
long max = (long) 60 * 24 * 60 * 60 * 1000;

并且你会得到你所期望的结果。

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