Reputation:
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
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