2

Why does this java code

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);

when run, output

1
1
107374182400
0

instead of the expected

1
1
107374182400
107374182400

output?

tomsv
  • 7,207
  • 6
  • 55
  • 88
  • 1
    That line you actually wrote `100` and not `100L`, Hence integer multiplication and resulted > integer capacity and resulted in zero, called as integer overflow. – Suresh Atta Dec 03 '13 at 14:19
  • possible duplicate of [How does Java handle integer underflows and overflows and how would you check for it?](http://stackoverflow.com/questions/3001836/how-does-java-handle-integer-underflows-and-overflows-and-how-would-you-check-fo) – Jeroen Vannevel Dec 03 '13 at 14:22
  • @JeroenVannevel That might be a duplicate, had I known it was an overflow situation before getting your answers. – tomsv Dec 03 '13 at 14:29
  • 1
    @dontomaso I think it was bad luck (or by design if this is a class assignment) that it is exactly 50 times the full integer swing otherwise it would have been more obvious that it was an overflow – Richard Tingle Dec 03 '13 at 14:35
  • possible duplicate of [Why do these two multiplication operations give different results?](http://stackoverflow.com/questions/12758338/why-do-these-two-multiplication-operations-give-different-results) – Dennis Meng Dec 03 '13 at 18:02

9 Answers9

6
 long a2 = 100L * 1024 * 1024 * 1024;

In this operation however at least one operand is long. hence the operation is carried out using 64-bit precision, and the result of the numerical operator is of type long. The other non-long operand are widened to type long by numeric promotion and resulted value gets stored to to variable a2.

 long a1 = 100 * 1024 * 1024 * 1024;

The constant expression of plain integer, the result of the expression was computed as a type int. The computed value however too large to fit in an integer and hence overflowed, resulting in 0 and gets stored to a1 variable.

Edit: As is asked in the following comment:

Why doesn't it go negative?

Because while in integer computation the second computation is equivalent to 25 * 2^32 where ^ has the power meaning and 2^32 integer value is 0. However, to explain why it's value is 0: In binary:

 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 is a negative integer(-2147483648) as the sign bit is 1 And hence 2 ^ 32 is just a multiplication of 2 to 2 ^ 31: a left shift and the sign bit will become 0 and hence the result is 0.

Check out the java language specification: 4.2.2: Integer operation for details.

Sage
  • 15,290
  • 3
  • 33
  • 38
  • Why doesn't it go negative? – Steve P. Dec 03 '13 at 14:35
  • 4
    @SteveP. Because 107374182400/2^32=25, **exactly**, it goes around 25 times to sit back at 0. Which I explain in detail [here](http://stackoverflow.com/a/20353700/2187042) – Richard Tingle Dec 03 '13 at 14:37
  • 1
    @RichardTingle you should your comment to your answer | that holds a key point in explanation – exexzian Dec 03 '13 at 14:39
  • Ah, missed that. Now it makes sense. – Steve P. Dec 03 '13 at 14:40
  • @RichardTingle, thanks for responding. I was busy with another answer though :P – Sage Dec 03 '13 at 14:43
  • @RichardTingle edit is not reflecting ? seems you are seriously switching between SO tabs :):) – exexzian Dec 03 '13 at 14:45
  • @RichardTingle No its ok now I was thinking that this answer is yours and I have already +1ed your answer – exexzian Dec 03 '13 at 14:51
  • @SteveP. sorry for late response, was busy with some other answer. Came back to answer your question. please check the edit – Sage Dec 03 '13 at 15:13
  • @sansix, check the edit of above answer. The reason is `2 ^ 32` is `0` while in integer computation – Sage Dec 03 '13 at 15:20
  • Hmm, but by this logic you could cast anything larger than 2^23 into `something * 2^32` but 6 * 1024 * 1024 * 1024 (aka 1.5*2^23) ends up as -2147483648, consistent with it rolling round again. And 7 * 1024 * 1024 * 1024 ==-1073741824 etc etc – Richard Tingle Dec 03 '13 at 15:36
  • @Sage I have already +1ed you mate :) ( providing specification link was good move) – exexzian Dec 03 '13 at 15:56
  • @RichardTingle, i have mentioned that the computation is in integer specifically and as it is being.My point is I see : `it will overflow 25 times and end up on precisely on 0` as a wrong explanation. Multiply a primary number like `101` to `2 ^ 31`: and although `101 * 2 ^ 31` is greater than `25 * 2 ^ 32`, the result of the computation will not be zero – Sage Dec 03 '13 at 17:01
  • 1
    @Sage `100 * 1024 * 1024 * 1024` will always be evaluated by JVM from left to right not the way you mentioned `100 * 1024 * 1024 * 1024 == 25 * 2^32` i.e. it is evaluated as `(((100 * 1024 ) * 1024) * 1024 )` as it is mentioned in http://docs.oracle.com/javase/specs/jls/se7/html/jls-15.html#jls-15.7 – Deepak Bhatia Dec 04 '13 at 09:16
  • i said they are equivalent. I didn't mention that their is an order. Do some calculation by writing a program. And you have posted your answer 1 hour later than mine. You have posted nothing more than what i and other answers have described and what We have linked **1 hour** before than you. What is the supposing meaning behind the downvote ? – Sage Dec 04 '13 at 09:29
  • 1
    @Sage the only reason is the explanation given by you for an answer why it evaluates down to `0` and if you read the link http://docs.oracle.com/javase/specs/jls/se7/html/jls-4.html#jls-4.2.2 the answer got by multiplication of `i*i` where `int i = 1000000;` is a negative number `-727379968` not `0` – Deepak Bhatia Dec 04 '13 at 09:42
  • @SteveP. specifically mentioned why *it is not negetive* why it is zero. And i focused on his question. which tell us that going to negative is seemingly expected but **why it is zero**. I have showed the evaluation. Your own mentioning of `result is 107374182400` no way differs from mine one: `the result is equivalent to 25 * 2 ^ 32`. And i have showed the complete calculation using even `2 ^ 31` where i specifically identified why the value is negative. Read the answer and comments more carefully before **downvoting others and editing your answer completely 16 hours later following others**. – Sage Dec 04 '13 at 09:55
5

107374182400 is exactly 25 times the full range of an integer (2^32), which means that if you try to fit it into an integer it will overflow. And because it would fit exactly 25 times it ends up precisely on 0 (this is a coincidence and other huge multiplications may end up either positive or negative). And you are using an integer right up to the point you cast to long

long a1 = 100 * 1024 * 1024 * 1024;

is equivalent to

int temp = 100 * 1024 * 1024 * 1024;
long a1 = (long)temp;

If you put a single long in the expression, it is forced to use long maths not integer maths which removes the problem

Community
  • 1
  • 1
Richard Tingle
  • 16,906
  • 5
  • 52
  • 77
  • ooppss I took `Sage'` answer as yours. yeah now can see change +1 – exexzian Dec 03 '13 at 14:48
  • @sansix With it's current +4 I wouldn't mind stealing it, but alas. Thanks for the +1 – Richard Tingle Dec 03 '13 at 14:50
  • Sorry was a bit late to respond with every one answer but: `which means that if you try to fit it into an integer it will overflow 25 times and end up on precisely on 0` this is not exactly the reason. `2 ^ 32` is `0` while computing in integer as i have mentioned in my answer – Sage Dec 03 '13 at 15:11
4

It might be that the expression on the right of a1 is first calculated as an int and later on converted to long. If it equals 0 as an int it'll stay 0 as a long

miau
  • 227
  • 2
  • 9
2

As per the documentation of Lexical Literals it is mentioned that,

The type of a literal is determined as follows:
- The type of an integer literal (§3.10.1) that ends with L or l is long (§4.2.1).
- The type of any other integer literal is int (§4.2.1).

Thus your expression, 100 * 1024 * 1024 * 1024 is evaluated as int primitive data type because l or L is not mentioned in any numeric value. and the result is 107374182400 i.e. in Binary it is 1 1001 0000 0000 0000 0000 0000 0000 0000 0000 and int is 32-bit so low 32-bit are taken as mentioned in Example 4.2.2-1. Integer Operations which results to 0

It is also mentioned in same documentation that,

If an integer operator other than a shift operator has at least one operand of type long, then the operation is carried out using 64-bit precision, and the result of the numerical operator is of type long. If the other operand is not long, it is first widened (§5.1.5) to type long by numeric promotion

It means any value in expression contains l or L then all the int values will be expanded to 64 bit.

EDIT In the comment it is also asked

Why doesn't it go negative?

I think it also answers the above question

Community
  • 1
  • 1
Deepak Bhatia
  • 6,230
  • 2
  • 24
  • 58
  • 1
    perfect explanation with correct java specifications why a numeric values is consider `int` not `byte`, `long` or `short` – Prateek Dec 04 '13 at 08:50
  • @SteveP it answers your question why value does not go negative – Deepak Bhatia Dec 04 '13 at 09:04
  • because, your answer has been later psoted by following others. You haven't mentioned anything more than other answer has already described. You have edited your answer completely after 16 hours later as your edit history tell us. And your first answer was: `The code long a1 = 100 * 1024 * 1024 * 1024; produces 0 because 100 * 1024 * 1024 * 1024 is manipulated by using the output as int and then it caste to long` was not meaningful at all. There is no reason to clutter the website with repetitive information – Sage Dec 04 '13 at 09:45
  • @Sage that is the only reason why I edited my answer to provide correct explanation after a long search in **JAVA Specification** why expression boils down to `int` expression not `byte`, `short`, `long` or any other – Deepak Bhatia Dec 04 '13 at 09:49
  • **That specification** has already been linked **16 hours** before you and the reason was also explained **16 hours** before you. Read all the answer which were completely right **16 hours** before yours one. – Sage Dec 04 '13 at 09:57
1

long a4 = 1L; //No problem in this

long a3 = 1; //here left side primitive is considered as integer and at the time of assignment it will be casted to long so again result is as expected

long a2 = 100L * 1024 * 1024 * 1024; (here you have used 100L so others will be type casted to Long so expected output)

long a1 = 100 * 1024 * 1024 * 1024; (as by default any primitive digit is considered as int in java, it will consider this as integer multiplication so it goes out of range and results in 0)

dev2d
  • 4,245
  • 3
  • 31
  • 54
0

reason is integer overflow
as output of 100 * 1024 * 1024 * 1024; is an integer(int) not long

and in long a2 = 100L * 1024 * 1024 * 1024; you are specifying that one of the value is long (here 100L) and multiplication with that value results in long value which gets correctly stored in a2

exexzian
  • 7,782
  • 6
  • 41
  • 52
0

Here's what you did : You assigned 100 * 1024 * 1024 * 1024 to a long data type but you didn' said that 100 * 1024 * 1024 * 1024 is a long value

By default java compiler thinks that its an integer. Since integer cannot hold that much value, it will show wrong result. Hope it helps !

Prashant Ghimire
  • 4,890
  • 3
  • 35
  • 46
0

In Java, if you have int * int, it will compute the output as an int. It only gives the result as a long if you do int * long. In your case, the 100 * 1024 * 1024 * 1024 has a result that overflows int.

So, adding a "L" makes the operand to be a long, and the computation stores the values in long. And of course, no overflow occurs and a correct result can be outputed (i.e. a2).

Siu
  • 1,422
  • 1
  • 12
  • 17
0

Number 3 worked because you specified a long type which is 100L. Thats why it is a long multiplication and could be stored. On the other hand number 4 is an integer multiplication with max value 2^32-1 thats why you got an overflow and the zero default valued appeared.

Shady Hussein
  • 513
  • 8
  • 24