【问题标题】:Scala Range.Double missing last elementScala Range.Double 缺少最后一个元素
【发布时间】:2016-09-23 07:32:26
【问题描述】:

我正在尝试创建一个在 [lower,upper) 范围内均匀分布的 numBins 数字列表。当然,存在浮点问题,这种方法不是最好的。然而,使用Range.Double 的结果让我感到惊讶,因为缺少的元素根本不接近上限。

设置:

val lower = -1d
val upper = 1d
val numBins = 11
val step = (upper-lower)/numBins   // step = 0.18181818181818182

问题:

scala>   Range.Double(lower, upper, step)
res0: scala.collection.immutable.NumericRange[Double] = NumericRange(-1.0, -0.8181818181818182, -0.6363636363636364, -0.45454545454545453, -0.2727272727272727, -0.0909090909090909, 0.09090909090909093, 0.27272727272727276, 0.4545454545454546, 0.6363636363636364)

问题:列表似乎少了一个元素。 0.8181818181818183 更进一步,小于 1。

解决方法:

Scala>   for (bin <- 0 until numBins) yield lower + bin * step
res1: scala.collection.immutable.IndexedSeq[Double] = Vector(-1.0, -0.8181818181818181, -0.6363636363636364, -0.4545454545454546, -0.2727272727272727, -0.09090909090909083, 0.09090909090909083, 0.2727272727272727, 0.4545454545454546, 0.6363636363636365, 0.8181818181818183)

此结果现在包含预期数量的元素,包括 0.818181..

【问题讨论】:

  • 对我来说很好(scala 2.11.8)。你运行的是什么版本的 scala?
  • 我刚刚将您的代码粘贴到我的 REPL (Scala 2.10.3...) 中,它按预期工作 - 我确实收到了 0.8181818181818182
  • 版本:Scala 版本 2.11.5(Java HotSpot(TM) 64 位服务器 VM,Java 1.8.0)
  • Scala 版本 2.13.2。 Range.Double 被删除了吗?有人可以建议替代 API

标签: scala floating-point double range


【解决方案1】:

我认为您的问题的根本原因是 toStringNumericRange 实现的一些功能

217  override def toString() = { 
218     val endStr = if (length > Range.MAX_PRINT) ", ... )" else ")" 
219     take(Range.MAX_PRINT).mkString("NumericRange(", ", ", endStr) 
220   } 

UPD:这与toString 无关。其他一些方法,例如 mapforeach 从返回的集合中剪切最后一个元素。

不管怎样,通过检查size 的集合你有 - 你会发现 - 所有元素都在那里。

您在解决方法示例中所做的 - 使用了不同的基础数据类型。

【讨论】:

  • 谢谢,进一步检查:.size 我得到 12 个元素。 .last 提供1dfor (i &lt;- rng) println(i) 提供与 toString 相同的元素。索引(尽管适用)允许召回第 9 个元素(0.636363..),但不能召回缺失的第 10 个元素(0.818181..)
  • 试试看.tail
  • Tail 包含所有元素。很有意思。这些方法怎么会漏掉元素?这似乎违反直觉,不违反文档吗?
  • 我建议您避免使用Range.Double。此功能存在一些错误。 issues.scala-lang.org/browse/SI-8782
  • 在与“NumericRange”类相关的代码中还有许多“TODO”标记。您最好在示例中使用lower to upper by step。它完全按照您的需要工作。
猜你喜欢
  • 2017-08-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-08-13
  • 1970-01-01
  • 2019-06-24
相关资源
最近更新 更多