Why two different answers are coming for the same value in case 2: on 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);
}
}
Answers are given below from Ideone.
Case 1:
size :549755813888
size :549755813888
Case 2:
size :2199023255552
size :0
The reason why you are seeing zero is because it's a Integer overflow. In this exact scenario you trigger the JLS Multiplication Operator which states that the lower end bits will be the result of a overflow.
For example
System.out.println((1025*1024*1024*1024*2));
System.out.println(Integer.toBinaryString(1025*1024*1024*1024*2));
Will print out
-2147483648 // Integer overflow
10000000000000000000000000000000 // Integer overflow
In your case
System.out.println((1024*1024*1024*1024*2));
System.out.println(Integer.toBinaryString(1024*1024*1024*1024*2));
It will print out
0 // still a overflow, but the lower ordered bits are 0, since we dont see trailing zero bits
0
So what exactly happens is that you calculation starts off with an Integer
size=1024*1024*1024*1024*2l;
If you don't state that it's a long, it will not handle it as such.
To fix it you have to use uppercase L or lowercase l at the first operand.
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));
The result is
2199023255552 // long value
100000000000000000000000000000000000000000
Case 1
1024 is an int. So 1024 * 1024 * 1024 is performed in int arithmetic, that is, in 32 bits. Since 1024 is 2^10, 1024 * 1024 * 1024 is 2^30, so it fits in a 32-bit int. Next you multiply by 512L, that is, a long (please use capital L; it’s so easy to misread a small l for digit 1). Therefore, 2^30 is converted to long and the two long values are multiplied. Result is 2^39, which fits in a long (would not have fit in an int). All is fine.
Case 2
1024 * 1024 * 1024 is 2^30 as before, and is an int as before. The next 1024 is in int too, so the next multiplication is done in 32-bit arithmetic and overflows because the result would have been 2^40, which cannot fit in. Since the number ends in 32 zeros, the result is 0. This is now converted to long (0L) so it can be multiplied by 2L. 0 * 2 is 0 (no matter if you do it in 32 or 64 bits).
Fix
As has been said, it’s technically enough to mark one of the constants as long (with the L), as long as you do it before the overflow happens. 1024 * 1024 * 1024 * 1024L * 2 or 1024L * 1024 * 1024 * 1024 * 2 should work. I do, however, prefer 1024L * 1024L * 1024L * 1024L * 2L. I find it easier to read and understand. Other options I find nice include 1L << 41 and 0x200_0000_0000.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With