Chapter 3: Comparing Floating Point Numbers

Comparing Floating-Point Numbers
Floating-point numbers have only limited precision, and calculations can introduce roundoff errors. Take a look at this example:

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 not 0 but " + d);

When comparing floating-point numbers, don’t test for equality.
Instead, check whether they are close enough.
In Java, we program the test as follows: x is close to 0 if
Math.abs(x) ≤ EPSILON
where we define

final double EPSILON = 1E-14;

Similarly, you can test whether two numbers are close to each other by checking whether their difference is close to 0.
| x – y | ≤ ε
However, this is not always good enough. Suppose x and y are rather large, say a few billion each. Then they could be the same, except for a roundoff error, even if their difference was quite a bit larger than 10^(-14)
To overcome this problem, you need to divide by the magnitude of the numbers before comparing how close they are. Here is the formula: x and y are close enough if

     
      | x - y |
    ------------  ≤ ε
     max(|x|,|y|)

The choice of EPSILON depends on your application. Let’s take a look at one possible value:

final double EPSILON = 1E-14;
Math.abs( x - y ) / Math.max(Math.abs( x ), Math.abs( y )) <= EPSILON;

 
Assignments:

1. What EPSILON would you choose to find out if these two pair of values are relatively equal?
Show your calculations and how you determine if they are equal or not. This is dependent on the application. Justify your EPSILON.

Are 1,000,000 and 1,000,001 equal?
Are 0.0000002 and 0.0000003 equal?

Is there one EPSILON that fits all expressions?

2. Write a program, FloatCompare_YI.java that reads in two floating-point numbers and tests (a) whether they are the same when rounded to two decimal places and (b) whether they differ by less than 0.01. Here are two sample runs.
Enter two floating-point numbers:
2.0
1.99998
They are the same when rounded to two decimal places. They differ by less than 0.01.
Enter two floating-point numbers:
0.999
0.991
They are different when rounded to two decimal places. They differ by less than 0.01.

3. Write a program that prints all real solutions to the quadratic equation
ax² + bx + c = 0. Read in a, b, c and use the quadratic formula. If the discriminant b² - 4ac is negative, display a message stating that there are no real solutions.
Implement a class QuadFormula_YI whose constructor receives the coefficients a, b, c of the quadratic equation. Supply methods getSolution1 and getSolution2 that get the solutions, using the quadratic formula.
Supply two methods

       boolean hasSolutions()

returns false if the discriminant is negative.

       boolean oneRealSolution()

returns false if the discriminant is negative. Implement this method using EPSILON to determine if discriminant is zero.