将数字类型转换为不带参数的Double

时间:2019-09-22 16:10:26

标签: scala

我正在尝试实现一种通用方法来计算任何类型的序列的平均值(例如:List,Array),该序列包含任何类型的数值(Int,Float,Double ...),如下所示:< / p>


 def mean[T <: Numeric[T]](data:Seq[T])(implicit number: Numeric[T]): T = {
      data.foldLeft(number.zero)(number.plus) / data.size
  }

但是,除法运算无法解决。这是因为数字类型未定义此操作(来自ScalaDoc)。 我想在进行除法运算之前将其转换为双精度,但是来自数字类型的方法toDouble(x:T)需要一个参数。 我已经看到Numeric [T]有一个名为NumericOps的类型成员,它确实实现了toDouble方法而没有接收任何参数。我可以叫这种方法吗?

3 个答案:

答案 0 :(得分:4)

这里是使用 Fractional 的示例,它将保留输入数字的正确精度,并且仅对数据进行一次遍历。但是,请注意,这仅适用于具有“精确” 划分的类型,例如ACTION_CREATE_DOCUMENT (Api level 19) FloatDouble。但是不适用于BigDecimalInt这样的数字类型。

Long

这已在 Scala def mean[T](data: Iterable[T])(implicit N: Fractional[T]): T = { import N._ val remaining = data.iterator @annotation.tailrec def loop(sum: T, count: Int): T = if (remaining.hasNext) loop(sum + remaining.next(), count + 1) else if (count == 0) zero else sum / fromInt(count) loop(zero, 0) } 上进行了测试。

答案 1 :(得分:3)

如果Double精度足够,请尝试

def mean[T](data: Seq[T])(implicit number: Numeric[T]): Double = {
  import number._
  val sum = data.foldLeft(zero)(plus) 
  toDouble(sum) / data.size
}

mean(Seq(1,2,3,4)) // 2.5

或使用Fractional(但不适用于Ints

def mean[T](data: Seq[T])(implicit number: Fractional[T]): T = {
  import number._
  val sum = data.foldLeft(zero)(plus)
  div(sum, fromInt(data.size))
}

mean(Seq(1.0,2,3,4)) // 2.5
mean(Seq(1,2,3,4))   // error: could not find implicit value for parameter number: Fractional[Int]

答案 2 :(得分:2)

除非必须使用Numeric,否则为什么不只使用Fractional,因为这会向Numeric添加div操作。

当他们谈论不同的选项时,您可能会发现这很有趣:

https://stackoverflow.com/a/40351867/67566