andyf andyf - 6 months ago 12
Java Question

Why java += get wrong result, and how can I prevent this?

Why java

+=
get wrong result, and how can I prevent this problem? (for example any way show
warning
in IDE?)

I tried eclipse & IntelliJ but both not show any warning.

Sample code:

{
long a = 20000000000000000L;
double b = 90.0;
a += b;
System.out.println(a); // 20000000000000088 NG
}

{
long a = 10000000000000000L;
double b = 90.0;
a += b;
System.out.println(a); // 10000000000000090 OK
}

{
long a = 20000000000000000L;
double b = 90.0;
a += (long) b;
System.out.println(a); // 20000000000000090 OK
}

Answer

According to the JLS, this compound assignment expression

a += b;

is equivalent to

a = (long) (a + b);

Since b is a double, binary numeric promotion occurs before the addition happens. Both operands are converted to double values and the addition happens with floating point arithmetic.

The value 20000000000000090 cannot be represented exactly as a double and therefore you lose precision, getting 20000000000000088 instead. It then gets cast back to a long which has enough precision to represent 20000000000000088.

Your second snippet produces 10000000000000090 which can be represented exactly as a double.

Your third snippet is equivalent to

a = (long) (a + (long) b);

which uses integer arithmetic. 20000000000000090 can be represented as a long.

I don't know of any tools to warn you about this.

Related: