简体   繁体   English

如何为 Double 生成 Scala 范围?

[英]How to generate Scala Range for Double?

I am not able to generate Scala ranges for Double.我无法为 Double 生成 Scala 范围。

I have read StackOverflow and there are many snippets which show double ranges but none of that works on my Scala REPL 2.13.0我已经阅读了 StackOverflow 并且有许多片段显示了双范围,但这些片段都不适用于我的 Scala REPL 2.13.0

9.474 to 49.474 by 1.0
1d to 1000d by 1d
(1.0 to 2.0 by 0.01)
            ^
       error: value to is not a member of Double

What is the reason I cannot use to and by to generate double ranges in my Scala REPL我不能使用 to 和 by 在我的 Scala REPL 中生成双范围的原因是什么

I am on a macOS with Scala 2.13.0我在使用 Scala 2.13.0 的 macOS 上

With Scala 2.12 I get a deprecation warning: 使用Scala 2.12,我会收到弃用警告:

scala> 9.474 to 49.474 by 1.0
<console>:12: warning: method to in trait FractionalProxy is deprecated (since 2.12.6): use BigDecimal range instead
       9.474 to 49.474 by 1.0

So maybe it is not supported anymore in 2.13. 因此,也许在2.13中不再受支持。 According to the warning you can do: 根据警告,您可以执行以下操作:

scala> BigDecimal(9.474) to BigDecimal(49.474) by BigDecimal(1.0)
res6: scala.collection.immutable.NumericRange.Inclusive[scala.math.BigDecimal] = NumericRange 9.474 to 49.474

This also works: 这也适用:

BigDecimal(9.474) to BigDecimal(49.474) by 1

If you do .foreach(println) on both versions you see that without BigDecimal the result looks not so great: 如果在两个版本上都使用.foreach(println) ,则会看到没有BigDecimal的结果看起来不太好:

9.474
10.474
..
31.474
32.474000000000004
33.474000000000004
...

From the Release Notes : 发行说明中

Assorted deprecated methods and classes throughout the standard library have been removed entirely. 整个标准库中已弃用的各种方法和类已完全删除。

You can always create your own function that will create Range (or Seq/Iterator) for you.您始终可以创建自己的 function,它将为您创建 Range(或 Seq/Iterator)。

// https://scastie.scala-lang.org/ZPfpF37bRlKfUPnMyOzJDw

import scala.util.Try

def rangeInclusiveDouble(from:Double, to:Double, by:Double = 1.0) = {
  assume(by != 0, "'by' cannot by 0")
  assume((to - from) * by > 0, "range has reversed order (arguments 'from', 'to' and 'by' will produce infinite range)")
  val check: Double => Boolean = if (by > 0) _ <= to else _ >= to
  Iterator.iterate(from)(_+by).takeWhile(check)
}

//usage example:
rangeInclusiveDouble(1.1, 5.1).toSeq
//List(1.1, 2.1, 3.1, 4.1, 5.1)
rangeInclusiveDouble(1.1, 2.1, 0.1).toSeq //here you will see why range over double is tricky!
//List(1.1, 1.2000000000000002, 1.3000000000000003, 1.4000000000000004,...
Try(rangeInclusiveDouble(5.0, 1.0).toSeq)
// Failure(java.lang.AssertionError: assumption failed: range has reversed order (arguments 'from', 'to' and 'by' will produce infinite range))
Try(rangeInclusiveDouble(5.0, 1.0, 0).toSeq)
//Failure(java.lang.AssertionError: assumption failed: 'by' cannot by 0)
rangeInclusiveDouble(5.0, 1.0, -1).toSeq
//List(5.0, 4.0, 3.0, 2.0, 1.0)

It has its own problems as you can see... but works if you are careful about range limits.如您所见,它有其自身的问题……但如果您注意范围限制,则可以使用。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM