0

I have been struggling to understand the concept of roundoff errors in Java with floating-point. While I understand that double is not supposed to be used for financial calculations, I don't understand why the 'd' variable does not come out to 0.0. How can I get this to print out the first println?

package zetcom;

public class floatingComparison {
public static void main(String[] args) {
    double r = Math.sqrt(2);
    double d = r * r - 2;

    if (d == 0)
    {
        System.out.println("sqrt(2) squared minus 2 is 0");
    }
    else
    {
        System.out.println("sqrt(2) squared minus 2 is " + d);
    }
  }
}

Any explanation would be appreciated.

mshades
  • 55
  • 7
  • Why don't you round it to 0 decimal places? I'm not sure what it's returning, but if you are ever working with floats it's a good idea to explicitly tell the variable how many decimal places you want it to have. Obviously, as the answers have stated, you can't have infinite precision in a finite system. – user1274820 Oct 17 '14 at 03:49
  • This is a question that has been asked ad nauseum - I'm voting to mark this as a dup of a similar question with a lot of well-written answers and links. – Krease Oct 17 '14 at 03:58
  • Note that `Math.sqrt(x*x)` always produce the same value as `x` (barring underflow or overflow). But that is a theorem. – Pascal Cuoq Oct 17 '14 at 07:15

2 Answers2

5

Short answer:

The square root of 2 requires an infinite number of digits -- that is, infinite precision. doubles have 52 bits of precision. That's a lot, but it's far, far short of infinite.

If you tried to represent 1/3 with two digits (0.33), you wouldn't be surprised at rounding errors, right? You'd multiply it by 3 and be not-at-all-surprised to get an answer of 0.99 instead of 1.0. It's the same thing exactly.

Digging a bit further...

What's a bit more un-intuitive is that numbers that can be represented with a infinite number of digits in base 10 might not be able to be represented by a finite number of digits in base 2 (which is what doubles and floats use). For instance, 1/10 is 0.1 in base 10, but it's 0.0001100110011... in base 2. So it will also be rounded off when you store it as a double, for the same reason as above: storing 1/10 in a finite number of digits in binary is as impossible as storing 1/3 in a finite number of digits in decimal.

Digging in even more...

And finally, you can look at it the other way around, too. While 1/3 is impossible to write in decimal with finite precision, it's just 0.1 in base 3.

yshavit
  • 42,327
  • 7
  • 87
  • 124
3

Floating point numbers in virtually all languages are always approximate (bar powers of 2), because they cannot be accurately represented in binary. This is due to how computers process information: in bits.

For instance, how do you represent .3 in binary? You're always going to get a round off error if you try to achieve maximum precision with floating point numbers due to them having to be represented in binary.

Tetramputechture
  • 2,911
  • 2
  • 33
  • 48