2.5. Comparing Floating-Point Numbers

Problem

You need to compare two floating-point numbers, 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
res38: Double = 0.2

But 0.1 plus 0.2 isn’t exactly 0.3:

scala> 0.1 + 0.2
res37: 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, ...

Get Scala Cookbook now with the O’Reilly learning platform.

O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.