Java长任务令人困惑

时间:2013-12-03 14:15:56

标签: java long-integer

为什么这个java代码

long a4 = 1L;
long a3 = 1;
long a2 = 100L * 1024 * 1024 * 1024;
long a1 = 100 * 1024 * 1024 * 1024;
System.out.println(a4);
System.out.println(a3);
System.out.println(a2);
System.out.println(a1);

运行时输出

1
1
107374182400
0

而不是预期的

1
1
107374182400
107374182400

输出

9 个答案:

答案 0 :(得分:5)

 long a2 = 100L * 1024 * 1024 * 1024;

在此操作中,至少有一个操作数为long。因此,操作使用64位精度执行,数值运算符的结果是long类型。另一个非长操作数是 扩展为通过数字促销键入long,结果值将存储到变量a2

 long a1 = 100 * 1024 * 1024 * 1024;

普通整数的常量表达式,表达式的结果计算为类型int。然而,计算的值太大而不适合整数并因此溢出,导致0并存储到a1变量。

编辑:正如以下评论中所述:

  

为什么不消极?

因为在整数计算中,第二次计算相当于25 * 2^32,其中^具有幂函数,2^32整数值为0 。但是,要解释为什么它的值是0:在二进制:

 100 * 1024 * 1024 * 1024 == 25 * 2^32;

 Integer.MAX_VALUE =  2 ^ 31 -1 = 0 11111111 11111111 11111111 1111111
 Integer.MAX_VALUE + 1 = 2 ^ 31 = 1 00000000 00000000 00000000 0000000 

2 ^ 31是一个负整数(-2147483648),因为符号位为1因此2 ^ 32只是2与{{1}的乘法}:左移,符号位将变为2 ^ 31,因此结果为0

查看java language specification: 4.2.2: Integer operation了解详情。

答案 1 :(得分:4)

107374182400正好是整数(2 ^ 32)的25倍,这意味着如果您尝试将其拟合为整数,它将overflow。并且因为它恰好适合25次,所以它恰好在0处结束(这是巧合,其他巨大的乘法可能最终为正或负)。并且你使用的是一个整数,直到你投射到长

的点
long a1 = 100 * 1024 * 1024 * 1024;

相当于

int temp = 100 * 1024 * 1024 * 1024;
long a1 = (long)temp;

如果在表达式中放置一个long,则强制使用长数学而不是整数数学来消除问题

答案 2 :(得分:3)

a1右侧的表达式可能首先计算为int,然后转换为long。如果它等于0int,它将0作为long

答案 3 :(得分:1)

long a4 = 1L; //没问题

long a3 = 1; //这里左侧原语被认为是整数,在赋值时它将被转换为long,所以结果再次如预期那样

long a2 = 100L * 1024 * 1024 * 1024;(这里你已经使用了100L所以其他人将被类型转换为Long所以预期的输出)

long a1 = 100 * 1024 * 1024 * 1024;(默认情况下,任何原始数字在java中都被视为int,它会将其视为整数乘法,因此它超出范围并导致0)

答案 4 :(得分:1)

根据documentation of Lexical Literals提到的,

  

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

因此,您的表达式100 * 1024 * 1024 * 1024被评估为int原始数据类型,因为任何数值都未提及lL。结果是 107374182400 ,即二进制文件中 1 1001 0000 0000 0000 0000 0000 0000 0000 0000 int为32位,所以32位如此低如Example 4.2.2-1. Integer Operations中所述,其结果为 0

在同一文档中也提到了

  

如果移位运算符以外的整数运算符至少有一个long类型的操作数,那么   该操作使用64位精度执行,数值运算符的结果为    类型长。如果另一个操作数不长,则首先将其扩展(第5.1.5节)以通过数字提升键入long

这意味着表达式中的任何值都包含lL,然后所有int值都将扩展为64位。

编辑the comment中,还会询问

  

为什么不消极?

我认为也回答了上述问题

答案 5 :(得分:0)

原因是整数溢出
因为100 * 1024 * 1024 * 1024;的输出是整数(int)而不是long

并且在long a2 = 100L * 1024 * 1024 * 1024;中您指定其中一个值为long(此处为100L),并且与该值相乘会产生long值,该值会正确存储在{{1}中}}

答案 6 :(得分:0)

这是你做的: 您已分配100 * 1024 * 1024 * 1024 对于长数据类型,但您没有说100 * 1024 * 1024 * 1024是一个长值

默认情况下,java编译器认为它是一个整数。由于整数不能保持那么多值,因此会显示错误的结果。希望能帮助到你 !

答案 7 :(得分:0)

在Java中,如果你有int * int,它会将输出计算为int。如果你做int * long,它只给出一个long的结果。 在您的情况下,100 * 1024 * 1024 * 1024的结果会溢出int。

因此,添加“L”使操作数变长,并且计算将值存储为long。当然,不会发生溢出,并且可以输出正确的结果(即a2)。

答案 8 :(得分:0)

Number 3工作,因为您指定了一个100L的long类型。这就是为什么它是一个很长的乘法并且可以存储。另一方面,数字4是一个整数乘法,最大值为2 ^ 32-1,这就是为什么出现溢出并出现零默认值。