Rounding errors in Java
Series Overview
This article is part of the series. Below are links to all posts in the series:What's inside this article
⌄
- How to use Python Fraction class
- Rational numbers Python implementation
- Convert fractions to decimals Python
- Python fraction arithmetic operations
Floating Away: Slightly Unstable World of Real Number Computations. Beating Rounding Errors with Java.
We had a discussion about the reasons behind rounding errors and floating-point arithmetic. We solved them in Python with Decimal class and Fraction class.
It’s time to say hello to Java.
Consider this:
double a = 0.7;
double b = 0.9;
double x = a + 0.1;
double y = b - 0.1;
And outputs:
System.out.println("x = " + x);
System.out.println("y = " + y );
System.out.println(x == y);
You might guess the output:
x = 0.7999999999999999
y = 0.8
false
We can fix this using a tolerance-based comparison:
double epsilon = 1e-10;
System.out.println(Math.abs(x - y) < epsilon);
Or by using BigDecimal class:
BigDecimal a = new BigDecimal("0.7");
BigDecimal b = new BigDecimal("0.9");
BigDecimal x = a.add(new BigDecimal("0.1"));
BigDecimal y = b.subtract(new BigDecimal("0.1"));
System.out.println(x.compareTo(y) == 0); // important!
Notice the way we compared x and y. It’s not a direct comparison using =, nor the equals().
Unfortunately, Java does not directly support handling repeating decimals. However, we still can make use of Fraction class of Apache commons-math library:
Fraction fraction1 = new Fraction(3, 4);
Fraction fraction2 = new Fraction(5, 6);
Fraction result = fraction1.add(fraction2);
System.out.println(result); // Output: 19/12
Let’s compare them:
Fraction fraction1 = new Fraction(1, 2);
Fraction fraction2 = new Fraction(2, 4);
System.out.println(fraction1.compareTo(fraction2) == 0); // Output: true