在尝试使用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)
的不同实例中包含的双精度总和,当然,除非还有另一种方法可以解决这个问题。
答案 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