为什么这个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
输出
答案 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
。如果它等于0
为int
,它将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
原始数据类型,因为任何数值都未提及l
或L
。结果是 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
这意味着表达式中的任何值都包含l
或L
,然后所有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,这就是为什么出现溢出并出现零默认值。