How to compare floating-point numbers in Scala

This is an excerpt from the Scala Cookbook (partially modified for the internet). This is Recipe 2.5, “Comparing Floating-Point Numbers in Scala.”

Problem

You need to compare two floating-point numbers in Scala, but as in some other programming languages, two floating-point numbers that should be equivalent may not be.

Solution

As in Java and many other languages, you solve this problem by creating a method that lets you specify the precision for your comparison. The following “approximately equals” method demonstrates the approach:

def ~=(x: Double, y: Double, precision: Double) = {
    if ( (x - y).abs < precision) true else false
}

You can use this method like this:

scala> val a = 0.3
a: Double = 0.3

scala> val b = 0.1 + 0.2
b: Double = 0.30000000000000004

scala> ~=(a, b, 0.0001)
res0: Boolean = true

scala> ~=(b, a, 0.0001)
res1: Boolean = true

Discussion

When you begin working with floating-point numbers, you quickly learn that 0.1 plus 0.1 is 0.2:

scala> 0.1 + 0.1
res0: Double = 0.2

But 0.1 plus 0.2 isn’t exactly 0.3:

scala> 0.1 + 0.2
res1: Double = 0.30000000000000004

This subtle inaccuracy makes comparing two floating-point numbers a real problem:

scala> val a = 0.3
a: Double = 0.3

scala> val b = 0.1 + 0.2
b: Double = 0.30000000000000004

scala> a == b
res0: Boolean = false

As a result, you end up writing your own functions to compare floating-point numbers with a precision (or tolerance).

As you saw in Recipe 1.11, you can define an implicit conversion to add a method like this to the Double class. This makes the following code very readable:

if (a ~= b) ...

Or, you can add the same method to a utilities object, if you prefer:

object MathUtils {
    def ~=(x: Double, y: Double, precision: Double) = {
        if ( (x - y).abs < precision) true else false
    }
}

which you can then invoke like a static method in Java:

println( MathUtils.~=(a, b, 0.000001) )

With an implicit conversion, the name ~= is very readable, but in a utilities object like this it doesn’t look quite right, so it might be better named approximatelyEqual, equalWithinTolerance, or some other name.

See Also

The Scala Cookbook

This tutorial is sponsored by the Scala Cookbook, which I wrote for O’Reilly:

You can find the Scala Cookbook at these locations:

Add new comment

Anonymous format

  • Allowed HTML tags: <em> <strong> <cite> <code> <ul type> <ol start type> <li> <pre>
  • Lines and paragraphs break automatically.