Java长任务令人困惑

tom*_*msv 1 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);
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)

输出?

Sag*_*age 5

 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仅仅是一个乘法22 ^ 31:左移位和符号位将成为0,因此其结果是0.

查看java language specification: 4.2.2: Integer operation详细信息.

  • @SteveP.因为107374182400/2 ^ 32 = 25,**正好是**,它大概是25次坐在0.我详细解释了[这里](http://stackoverflow.com/a/20353700/2187042) (4认同)

Ric*_*gle 5

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,从而消除了问题