Floating-Point Precision (0.1 + 0.2)
Problem
Read three decimal numbers x, y and z. Print two lines. The first line is exact: true if x + y == z (compared with ==), else exact: false. The second line is close: true if the difference between x + y and z is less than 0.000000001, else close: false. Example: 0.1 0.2 0.3 gives exact: false and close: true.
Constraints
- Inputs are decimal numbers with at most 15 significant digits
Examples
Input
0.1 0.2 0.3
Output
exact: false close: true
Solutions
Computers store decimals in binary. Numbers like 0.1 have no exact binary form, like 1/3 has no exact decimal form. So never compare decimals with ==. Compare with a small tolerance.
/*
* Problem : Compare a decimal sum with a target.
* Input : Three decimal numbers x, y, z.
* Output : Two lines: exact and close.
* Approach: Compare with a small tolerance.
* Time : O(1)
* Space : O(1)
* Java : 8 or newer.
*/
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
double x = Double.parseDouble(scanner.next());
double y = Double.parseDouble(scanner.next());
double z = Double.parseDouble(scanner.next());
// Step 1: Add the two numbers. The result can have a tiny error.
double sum = x + y;
// Step 2: Compare with == . This is exact, so tiny errors make it false.
boolean exact = (sum == z);
// Step 3: Compare with a tolerance. This is the correct way for decimals.
boolean close = Math.abs(sum - z) < 1e-9;
// Step 4: Print both answers.
System.out.println("exact: " + exact);
System.out.println("close: " + close);
}
}
Hints (2)
- Is 0.1 exactly stored in binary?
- How can we say two decimals are almost equal?