为什么这个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);
Run Code Online (Sandbox Code Playgroud)
运行时,输出
1
1
107374182400
0
Run Code Online (Sandbox Code Playgroud)
而不是预期的
1
1
107374182400
107374182400
Run Code Online (Sandbox Code Playgroud)
输出?
long a2 = 100L * 1024 * 1024 * 1024;
Run Code Online (Sandbox Code Playgroud)
但是在这个操作中至少有一个操作数long.因此,操作使用64位精度执行,并且数值运算符的结果是类型long.另一个非长操作数被扩展为long通过数字提升键入,结果值被存储到变量a2.
long a1 = 100 * 1024 * 1024 * 1024;
Run Code Online (Sandbox Code Playgroud)
普通整数的常量表达式,表达式的结果被计算为一个类型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
Run Code Online (Sandbox Code Playgroud)
2 ^ 31是负整数(-2147483648)作为符号位是1,因此2 ^ 32仅仅是一个乘法2到2 ^ 31:左移位和符号位将成为0,因此其结果是0.
查看java language specification: 4.2.2: Integer operation详细信息.
107374182400 正好是整数 (2^32) 全范围的 25 倍,这意味着如果您尝试将其放入整数,它将溢出。并且因为它恰好适合 25 次,所以它最终精确地为 0(这是一个巧合,其他巨大的乘法可能最终为正或负)。并且您一直使用整数直到您将其转换为 long
long a1 = 100 * 1024 * 1024 * 1024;
Run Code Online (Sandbox Code Playgroud)
相当于
int temp = 100 * 1024 * 1024 * 1024;
long a1 = (long)temp;
Run Code Online (Sandbox Code Playgroud)
如果你在表达式中加入一个 long ,它会被迫使用 long maths 而不是 integer maths,从而消除了问题