17
long m = 24 * 60 * 60 * 1000 * 1000;

The above code creates overflow and doesn't print the correct result.

long m2 = 24L * 60 * 60 * 1000 * 1000;
long m3 = 24 * 60 * 60 * 1000 * 1000L;

The above 2 lines print the correct result.

My questions are-

  1. Does it matter to the compiler which I use, m2 or m3?
  2. How does java starts multiplying? Left to right or right to left? Does 24*60 gets computed first or 1000*1000?
gunr2171
  • 16,104
  • 25
  • 61
  • 88
rents
  • 768
  • 1
  • 7
  • 22
  • 1
    oops- long m2 = 24L * 60 * 60 * 1000 * 1000*1000*1000; long m3 = 24 * 60 * 60 * 1000 * 1000*1000* 1000L; m2 and m3 don't give same result when mutiplied more say by a factor of 1000*1000. So it seems multiplication occurs from left to right. – rents Jun 02 '15 at 20:55
  • 2
    Right, use `m2` so every intermediate multiplication is promoted to `long`. Multiplication is left-associative, so it goes from left to right. – GriffeyDog Jun 02 '15 at 21:06
  • Multiplication is associative, so the order wouldn't matter. However it is computed left to right in cases it does matter such as calling methods which return a number. – Peter Lawrey Jun 02 '15 at 23:55
  • Does the concern relate **only** to overflow? The numbers appear to be time related, so left-hand values seem fixed. Or is there a performance element also? Millions of calculations? – user2338816 Jun 03 '15 at 00:48

6 Answers6

20

In this case -

long m = 24 * 60 * 60 * 1000 * 1000;  

The right of the assignment is evaluated first. At right there is no long type data. All are int. So the JVM try to fit the result in an int then the overflow occurred.

And in the second case -

long m2 = 24L * 60 * 60 * 1000 * 1000;
long m3 = 24 * 60 * 60 * 1000 * 1000L;

Here one operand of the multiplication is long. So other are prompted to long automatically. The result is trying to fit to a long. Finally the assignment is done with m2 and m3.

And yes the associativity of multiplication from left to right - means the left operand is taken first. And Based on this fact I think in this scenario we should use -

long m2 = 24L * 60 * 60 * 1000 * 1000;  

this statement, since at this statement the promotion to long taken places earlier which reduces the risk of overflow.

Razib
  • 10,965
  • 11
  • 53
  • 80
16

I would use the m2 line instead of the m3 line.

Java evaluates the multiplication operator * from left to right, so 24 * 60 is evaluated first.

It just so happens that 24 * 60 * 60 * 1000 (one 1000) doesn't overflow, so that by the time you multiply by 1000L (the second 1000), the product is promoted to long before multiplying, so that overflow doesn't take place.

But as you mentioned in your comments, more factors can cause overflow in the int data type before multiplying the last long number, yielding an incorrect answer. It's better to use a long literal for the first (left-most) number as in m2 to avoid overflow from the start. Alternatively, you can cast the first literal as a long, e.g. (long) 24 * 60 * ....

rgettman
  • 176,041
  • 30
  • 275
  • 357
9

Since expressions are evaluated from left to right, I would prefer your first solution (m2 = ...).

Reasoning: Let's look at a slightly different example.

long g = Integer.MAX_VALUE * 2 * 2L;

This expression will evaluate to -4 since only the last multiplication casts the first expression to long (which is -2 at this point in time, because both operands are int). If you write

long g = Integer.MAX_VALUE * 2L * 2;

instead, g will hold the expected value of 8589934588 since the first multiplication yields a result of type long.

Turing85
  • 18,217
  • 7
  • 33
  • 58
6

Multiplying works from left to right, and int * int produces int. So

24 * 60 * 60 * 1000 * 1000

is same as

(((24 * 60)* 60) * 1000) * 1000

which gives us

(((1440)* 60) * 1000) * 1000
((  86400   ) * 1000) * 1000
(    86400000       ) * 1000

and finally because of integer overflow (since 86400000000 is too big for integer which max value is 2147483647) result will be

500654080

You can eliminate integer overflow by using long as one of arguments (int * long and long * int produces long).

In this case you can do it at start like you did in case of m2: 24L * 60 which will produce long 1440L which again will be multiplied by int 60 producing new long, and so on, producing only long values.

m3 case works here because you are multiplying 86400000 by 1000L which means that you are avoiding integer overflow since result will be long.

Pshemo
  • 122,468
  • 25
  • 185
  • 269
4

Let's multiply more numbers, this line will overflow even there is a 1000L:

long m3 = 24 * 60 * 60 * 1000 * 1000 *  1000 * 1000L;

While this will give correct result:

long m3 = 24L * 60 * 60 * 1000 * 1000 *  1000 * 1000;

So we are sure that java start multiplying from left to right and we have to start with Long from the left to prevent overflow.

54l3d
  • 3,913
  • 4
  • 32
  • 58
2

This is because when we use long as one operand the other all int type operand get prompted to long.

The expression in java evaluated from left to right.

masud.m
  • 145
  • 13