双打列表中的foldLeft返回奇怪的值

时间:2015-12-23 15:39:57

标签: scala floating-point

在尝试使用foldLeft对不同实例中包含的双精度列表求和时,我遇到了一个奇怪的问题。经过调查,似乎即使在使用简单双打列表时,问题仍然存在:

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

我在这里做错了什么?

注意: foldLeft这里是必要的,因为我想要实现的是case class SomeClass(value: Double)的不同实例中包含的双精度总和,当然,除非还有另一种方法可以解决这个问题。

1 个答案:

答案 0 :(得分:3)

  

我在这里做错了什么?

当你需要这种精确度时使用双打。这对foldLeft来说不是问题。您遇到了浮点舍入错误。问题是某些数字需要二进制的非常长(或无限)表示,这意味着它们需要以二进制形式截断。当转换回十进制时,该二进制舍入错误表面。

使用BigDecimal代替,因为它是为了任意精度而设计的。

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

或者简单地说:

scala> list.sum
res4: BigDecimal = 464.40