I have code like this :
int a = 629339;
int b = 4096;
long res = a*b;
The result is -1717194752
but if I add one manual cast
a*b
is an integer, not a long.
Because it's only an integer, it has already wrapped around the 32-bit limit.
Casting this integer back to long will not magically recover that data.
You have to break the assignment statement into its parts to understand what is doing on:
long res = a*b;
Step 1 is to get the values of a
and b
.
Step 2 is to evaluate a * b
. Since a
and b
are both int
s, this is an int
multiplication. So we multiply 629339
by 629339
which would be 2577772544
.
Unfortunately, 2577772544
is larger than the largest possible Java int
value ... so the multiplication operation silently overflows ... and we get -1717194752
instead.
Step 3 we assign the value of the RHS to the LHS. Since the RHS is int
and the LHS is float
, the JLS says we perform a primitive widening conversion ... which simply turns -1717194752
into a long
with the same value. The widened value is then assigned to res
.
To get the answer that you are expecting, we have to force multiplication to be performed using long
arithmetic. For example:
long res = ((long) a) * b;
In this case, we have a multiplication of a long
by an int
, and this is handled by widening the int
to a long
and performing a long
multiply. This no longer overflows (because 2577772544
is well below the largest long
value), so when we finally assign the value to res
, it is the number that you were expecting.
long res = a*b;
a*b
will be treated as integer unless you add 'l' at end (or) cast.
As per java tutorial
The int data type is a 32-bit signed two's complement integer. It has a minimum value of -2,147,483,648 and a maximum value of 2,147,483,647 (inclusive). For integral values, this data type is generally the default choice unless there is a reason (like the above) to choose something else.