user908853
user908853

Reputation:

foldLeft on list of Doubles returns strange value

I'm running into a strange issue when trying to sum a list of doubles that are contained in different instances using foldLeft. Upon investigation, it seems that even when working with a list of simple doubles, the issue persists:

val listOfDoubles = List(4.0, 100.0, 1.0, 0.6, 8.58, 80.0, 22.33, 179.99, 8.3, 59.0, 0.6)
listOfDoubles.foldLeft(0.0) ((elem, res) => res + elem) // gives 464.40000000000003 instead of 464.40

What am I doing wrong here?

NOTE: foldLeft here is necessary as what I'm trying to achieve is a sum of doubles contained in different instances of a case class SomeClass(value: Double), unless, of course, there is another method to go about this.

Upvotes: 0

Views: 422

Answers (1)

Michael Zajac
Michael Zajac

Reputation: 55569

What am I doing wrong here?

Using doubles when you need this kind of precision. It's not a problem with foldLeft. You're suffering from floating point rounding error. The problem is that some numbers need very long (or infinite) representations in binary, which means that they need to be truncated in binary form. And when converted back to decimal, that binary rounding error surfaces.

Use BigDecimal instead, as it is designed to for arbitrary precision.

scala> val list: List[BigDecimal] = List(4.0, 100.0, 1.0, 0.6, 8.58, 80.0, 22.33, 179.99, 8.3, 59.0, 0.6)
list: List[BigDecimal] = List(4.0, 100.0, 1.0, 0.6, 8.58, 80.0, 22.33, 179.99, 8.3, 59.0, 0.6)

scala> list.foldLeft(BigDecimal(0.0))(_ + _)
res3: scala.math.BigDecimal = 464.40

Or simply:

scala> list.sum
res4: BigDecimal = 464.40

Upvotes: 2

Related Questions