2

Why do I get different results when printing out z as shown in the following code snippet?
It seems that the compiler cuts in the second "print" all positions after '2'... Thank you for help!

double z = 1.0;
z = z + 0.1;
z = z + 0.1;
System.out.print("z := "+z);
System.out.print(" # z:= "+((0.1+0.1)+(1.0)));

Output:

z := 1.2000000000000002 # z:= 1.2
almightyGOSU
  • 3,731
  • 6
  • 31
  • 41
Karla
  • 37
  • 1
  • 3
    Actually, it's not the same code. You should compare with 1.0+0.1+0.1. – ericbn Jun 06 '15 at 11:47
  • Read [What Every Computer Scientist Should Know About Floating-Point Arithmetic](http://download.oracle.com/docs/cd/E19422-01/819-3693/ncg_goldberg.html) – ericbn Jun 06 '15 at 11:51

3 Answers3

2

The first code does 1.0 + 0.1 (intermediate result is 1.1) + 0.1. Second code does 0.1 + 0.1 (intermediate result is 0.2) + 1.0. Because of floating-point precision, that can't represent every number perfectly, you get different results.

double z = 1.0;
z = z + 0.1;
System.out.println(z);
z = z + 0.1;
System.out.println(z);
z = 0.1;
z = z + 0.1;
System.out.println(z);
z = z + 1.0;
System.out.println(z);

Output:

1.1
1.2000000000000002
0.2
1.2

http://ideone.com/XGsRRj

Read more at the http://floating-point-gui.de/

ericbn
  • 10,163
  • 3
  • 47
  • 55
1
double z = 1.0;
z = z + 0.1;
z = z + 0.1;

Printing z displays a value different than 1.2 because the result of adding 1.0 to 0.1 twice cannot be represented exactly in a double.

System.out.print(" # z:= "+((0.1+0.1)+(1.0)));

This prints # z:= 1.2 because " # z:= "+((0.1+0.1)+(1.0)) is treated as a constant string by the compiler and replaced directly with # z:= 1.2 in the compiled code. In other words, this statement is exactly equivalent to:

System.out.print(" # z:= 1.2");
M A
  • 71,713
  • 13
  • 134
  • 174
  • 1
    why ***adding 1.0 to 0.1 twice cannot be represented exactly in a double.***? – Lrrr Jun 06 '15 at 11:43
  • @Lrrr because of the way a floating point value is stored in binary? – almightyGOSU Jun 06 '15 at 11:44
  • @Gosu the problem with this answer is that it didnt explain the main question, the main question is exactly the part that I highlighted! – Lrrr Jun 06 '15 at 11:46
  • @Lrrr That is answered in the duplicate. This answer points to a difference in how the two versions are compiled, which subsequently affect the result: a computed result vs a string literal placed by the compiler. – M A Jun 06 '15 at 12:24
0

Use BigDecimal to get exact calculation results. Binary formats like float and double might have better Performance but lead to unexpected results when converting them into decimal numbers.

Some numbers cannot be exactly represented in binary. We all know that kind of problem, when trying to write "a third" in decimal representation (0.33333... never ending).

The example code:

BigDecimal z = new BigDecimal("1.0");
z = z.add(new BigDecimal("0.1"));
z = z.add(new BigDecimal("0.1"));
System.out.print("z := "+z);
System.out.print(" # z:= "+((0.1+0.1)+(1.0)));

Output:

z := 1.2 # z:= 1.2

run the code online at http://ideone.com/vTVIK7

slartidan
  • 20,403
  • 15
  • 83
  • 131