我正在尝试实现一种通用方法来计算任何类型的序列的平均值(例如: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
方法而没有接收任何参数。我可以叫这种方法吗?
答案 0 :(得分:4)
这里是使用 Fractional 的示例,它将保留输入数字的正确精度,并且仅对数据进行一次遍历。但是,请注意,这仅适用于具有“精确” 划分的类型,例如ACTION_CREATE_DOCUMENT (Api level 19)
,Float
和Double
。但是不适用于BigDecimal
或Int
这样的数字类型。
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操作。
当他们谈论不同的选项时,您可能会发现这很有趣: