Scala 迭代和范围中的精度错误

Precision errors in Scala iterate and range

我正在尝试构建一个具有范围和步骤的双打集合。当我使用 Array.iterate 方法时,出现奇怪的浮点错误,例如:

scala> Array.iterate[Double](0.0, 10)(0.1+)
res0: Array[Double] = Array(0.0, 0.1, 0.2, 0.30000000000000004, 0.4, 0.5, 0.6, 0.7, 0.7999999999999999, 0.8999999999999999)

小步长的小范围会导致如此不精确,这似乎很奇怪。我知道还有其他方法可以做到这一点(例如 Array.iterate[Int](0, 10)(1+).map(i => i.toDouble / 10.0)),但令我感到困惑的是内置的收集方法会执行得如此糟糕。这是有原因的还是我是个傻瓜,做错了?

这是浮点运算基本限制的症状,与集合无关:

scala> 0.2 + 0.1
res0: Double = 0.30000000000000004

有很多帖子解释了为什么会这样:

尝试使用 BigDecimal:

scala> val r = BigDecimal(0) to BigDecimal(1) by BigDecimal(0.1)

scala> println(r)
NumericRange(0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0)