乘法奇怪的输出

时间:2013-12-17 10:07:57

标签: java

long thirtyDayInMillis = 30 * 24 * 60 * 60 * 1000;

它应返回2592000000,但会返回-1702967296

但如果我将声明分成两个陈述。

long dayInMillis = 24 * 60 * 60 * 1000;
long thirtyDayInMillis = 30 * dayInMillis;

返回正确的值。

为什么它会为-1702967296返回30 * 24 * 60 * 60 * 1000

5 个答案:

答案 0 :(得分:12)

默认情况下,Java中的数字文字是int。因此,第一个乘法的各个部分都是int s,而不是long s,因此它们会溢出(数字太大而无法存储在int中)。当你分解它时,你会在它溢出之前将值转换为long

你可以通过在文字中添加L来解决这个问题,使它们变长;只有第一个是您真正需要的,因为30L * 24的结果将是long,依此类推:

thirtyDayInMillis = 30L * 24 * 60 * 60 * 1000;

请注意,我将L放在文字的第一个上。这是因为乘法从左到右进行,所以我们要从一开始就确保我们使用的是long值,而不是int值。例如,它的处理方式如下:

thirtyDayInMillis = (((30L * 24) * 60) * 60) * 1000;

首先30L * 24完成,然后结果为* 60,依此类推。因此,如果早期的那些(没有L仍然以int值完成)溢出,结果将是错误的。

你的特定表达式在最后一次乘法之前不会溢出,但让我们使用先前会溢出的值:

thirtyDayInMillis = 1000 * 24 * 6000 * 7000 * 30;

这给了我们(不正确的)结果-864731136而不是30240000000000。现在让我们把L放在错误的地方:

thirtyDayInMillis = 1000 * 24 * 6000 * 7000 * 30L;
// L in wrong place ----------------------------^

我们得到-39519436800。把它放在正确的地方:

thirtyDayInMillis = 1000L * 24 * 6000 * 7000 * 30;

...我们得到30240000000000

答案 1 :(得分:2)

您正面临整数溢流最常见的问题,
使用此

long thirtyDayInMillis = 1L * 30 * 24 * 60 * 60 * 1000;

根据documentation of Lexical Literals提到的,

  

文字的类型确定如下:
    - 以L或l结尾的整数文字(§3.10.1)的类型很长(§4.2.1)。
    - 任何其他整数文字的类型是int(§4.2.1)。

因此,您的表达式30 * 24 * 60 * 60 * 1000被评估为int原始数据类型,因为任何数值都未提及lL。结果是 2,592,000,000
即在二进制文件中,它是 1001 1010 0111 1110 1100 1000 0000 0000 ,而int是32位,因此Example 4.2.2-1. Integer Operations中提到的32位如此低,导致 {{ 1}} ,因为最重要的位用于表示符号。

答案 2 :(得分:1)

你应该这样做:

long thirtyDayInMillis = 30L * 24 * 60 * 60 * 1000;

Java中数字的默认值为int。因此,当您执行30 * 24 * 60 * 60 * 1000时,您将获得int计算,这会溢出。

请参阅docs

  

如果整数字面以字母 L l 结尾,则其长度为long;   否则为int 类型。建议您使用鞋面   大小写字母L因为小写字母l很难区分   从数字1。

答案 3 :(得分:0)

尝试long thirtyDayInMillis = 30 * 24 * 60 * 60 * 1000L;

默认情况下,最后将其视为int添加L,让编译器知道您正在传递long值,但正如Tim B指出*它的危险性因为30 * 24 * 60 * 60将以整数形式处理,仅用于最后一次乘法转换为long *

这样做

long thirtyDayInMillis = 30L * 24 * 60 * 60 * 1000;

答案 4 :(得分:0)

这是因为你正在乘以最大值为2147483647的整数 等式的右边保持int类型。 因此,只需尝试通过向其添加“l”来生成long类型的乘数之一,您将获得正确的结果 的 e.g。 long threeDayInMillis = 30l * 24 * 60 * 60 * 1000;