2016-05-25 93 views
2

我试图创建一个在范围[lower,upper]范围内均匀间隔的numBins数字列表。当然,还有浮点问题,这种方法并不是最好的。然而,使用Range.Double的结果令我惊讶,因为缺失的元素根本不接近上限。Scala 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 ..

+0

适合我(scala 2.11.8)。你运行的是什么版本的scala? – Marth

+0

我刚刚将你的代码粘贴到我的REPL(Scala 2.10.3 ...)中,它按预期工作 - 我确实得到了'0.8181818181818182'。 –

+0

版本:Scala版本2.11.5(Java HotSpot(TM)64位服务器虚拟机,Java 1.8.0) – blitzen

回答

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收藏 - 你会发现 - 所有元素都在那里。

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

+0

感谢您进一步检查:使用'.size'我可以获得12个元素。 '.last'给出'1d'。 'for(i < - rng)println(i)'给出与toString相同的元素。索引(尽管适用)允许召回第9个元素(0.636363 ..)但不是失踪的第10个(0.818181 ..) – blitzen

+0

尝试检查'.tail' – Rumoku

+0

尾部包含所有元素。多么有趣。这些方法如何错过元素?这似乎与直觉相反,是不是违背了文档? – blitzen