几何平均值的安全计算

时间:2016-06-09 00:53:02

标签: floating-point average precision numerical-methods

我正在寻找一个理由选择以下方法之一来计算一系列浮点x的几何平均值:

  1. 取每个x的第n个根,然后将它们全部加上
  2. 将所有这些相乘,然后取nth root
  3. 我听说过浮点数,乘法和除法输入的信息少于加法和减法。因此,我不考虑总和指数技巧。

    我应该通过1还是2计算几何平均值,为什么?

    更新1,回应评论:

    所有x小于1且精度为double。它们的数量级在10 ^ -1到10 ^ -6之间。请假设最常用的计算第n个根的方法,因为我使用的是编程语言的内置函数。由于所有值都小于1,我担心下溢(?)而不是溢出。您可以假设x系列的长度为10 ^ 8

1 个答案:

答案 0 :(得分:5)

通常,在一系列浮点运算中也涉及诸如平方根或立方根之类的收缩操作,从精度的角度来看,最后执行收缩操作是有利的。例如,1.0/sqrt(x)sqrt(a*b)更准确,sqrt(a)*sqrt(b)cbrt(a*b*c)更准确,cbrt(a)*cbrt(b)*cbrt(c)binary64更准确。< / p>

因此,除非存在溢出或下溢所选浮点格式的危险,例如IEEE-754 double(例如C / C ++中的pow()),否则在中间计算中,应该选择方法[2]。与准确性相关的其他方面:如果 n -th root是通过取幂计算的,例如C / C ++中的fma(),则每个计算的根都会引入额外的错误,如下所述:我对this question的回答中的立方根。最后, n -th root的计算速度将慢于乘法,因此在结束时仅与最终根计算相乘也将是一种性能优越的方法。

通过使用补偿产品(类似于Kahan summation提供的补偿加法),方法[2]可以获得非常准确的结果。有关详细信息,请参阅以下文章:

Stef Graillat,“准确的浮点产品和指数”, IEEE计算机交易,Vol。 58,第7期,2009年7月,第994-1000页(online

这种补偿产品可以在硬件中提供FMA(融合乘法 - 加法)运算的系统上特别有效地计算。所有常见的现代处理器架构(包括CPU和GPU)都是如此。 C / C ++通过标准数学函数fmaf()frexp()提供对此的便捷访问。

更新:Asker在评论中澄清说,由于10 [sup> 8 因素在[10 -6]中有大约10个因素,因此下溢的风险迫在眉睫sup>,10 -1 ]。 @Yves Daoust在评论中提到的一种可能的解决方法是将因子分为尾数和指数,并分别累积它们。这是否实用将取决于浮点环境。虽然C和C ++为执行此拆分提供了标准函数{{1}},但此函数可能不会非常快。