为什么在案例2中对于相同的值有两个不同的答案:在Java 7上?
class Ideone
{
public static void main (String[] args) throws java.lang.Exception
{
System.out.println("Case 1:");
long size=(long)1<<39;
System.out.println("size :"+size);
size=1024*1024*1024*512l;
System.out.println("size :"+size);
System.out.println("Case 2:");
size=(long)1<<41;
System.out.println("size :"+size);
size=1024*1024*1024*1024*2l;
System.out.println("size :"+size);
}
}
以下是Ideone的答案。
Case 1:
size :549755813888
size :549755813888
Case 2:
size :2199023255552
size :0
答案 0 :(得分:4)
你看到零的原因是因为它是一个整数溢出。在这种情况下,您会触发JLS Multiplication Operator,它指出低端位将是溢出的结果。
例如
System.out.println((1025*1024*1024*1024*2));
System.out.println(Integer.toBinaryString(1025*1024*1024*1024*2));
将打印出来
-2147483648 // Integer overflow
10000000000000000000000000000000 // Integer overflow
在你的情况下
System.out.println((1024*1024*1024*1024*2));
System.out.println(Integer.toBinaryString(1024*1024*1024*1024*2));
它会打印出来
0 // still a overflow, but the lower ordered bits are 0, since we dont see trailing zero bits
0
那么究竟发生的是你的计算以一个整数开始
size=1024*1024*1024*1024*2l;
如果你没有声明它很长,它就不会这样处理它。
要解决此问题,您必须在第一个操作数处使用大写L
或小写l
。
size=1024L*1024*1024*1024*2l;
System.out.println((1024L*1024*1024*1024*2l));
System.out.println(Integer.toBinaryString(1024L*1024*1024*1024*2l)); // will not work, because the compiler knows it's a long
System.out.println(Long.toBinaryString(1024L*1024*1024*1024*2l));
结果是
2199023255552 // long value
100000000000000000000000000000000000000000
答案 1 :(得分:2)
案例1
1024是int
。因此,在int
算术中执行1024 * 1024 * 1024,即32位。由于1024是2 ^ 10,1024 * 1024 * 1024是2 ^ 30,因此它适合32位int
。接下来,你乘以512L,即long
(请使用大写L;它很容易误读数字1的小l)。因此,2 ^ 30转换为long
,并且两个long
值相乘。结果是2 ^ 39,它适合long
(不适合int
)。一切都很好。
案例2
1024 * 1024 * 1024与之前一样是2 ^ 30,与以前一样是int
。接下来的1024也在int
,所以下一个乘法是在32位算术中完成并且溢出,因为结果将是2 ^ 40,这是不适合的。因为数字以32个零结束,结果现在转换为long
(0L),因此它可以乘以2L。 0 * 2为0(无论是32位还是64位)。
<强>修正强>
如前所述,只要在溢出发生之前执行此操作,技术上就足以将其中一个常量标记为long
(使用L)。 1024 * 1024 * 1024 * 1024L * 2
或1024L * 1024 * 1024 * 1024 * 2
应该有效。不过,我更喜欢1024L * 1024L * 1024L * 1024L * 2L
。我发现阅读和理解更容易。我觉得不错的其他选项包括1L << 41
和0x200_0000_0000
。