几何平均数的安全计算

Safe computation of Geometric Mean

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

  1. 对每个 x 取 n 次根,然后将它们相乘
  2. 将它们全部相乘,然后取n次方根

我听说对于浮点数,乘法和除法丢失的信息少于加法和减法。因此我不考虑和指数技巧。

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


更新1,回复评论:

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

一般来说,在一系列浮点运算中,还涉及平方根或立方根等收缩运算,从精度的角度来看,最后进行收缩运算是有利的。例如,sqrt(1.0/x)1.0/sqrt(x)更准确,sqrt(a*b)sqrt(a)*sqrt(b)更准确,cbrt(a*b*c)cbrt(a)*cbrt(b)*cbrt(c)更准确。

因此,除非存在上溢或下溢所选浮点格式的危险,例如 IEEE-754 binary64(例如 C/C++ 中的 double ), 在中间计算时,应选择方法[2]。与准确性相关的其他方面:如果 n-th 根是通过求幂计算的,例如 C/C++ 中的 pow(),则每次计算都会引入额外的错误根,正如我在对 this question 的回答中对立方根的解释。最后,n-th 根的计算将比乘法慢,因此在最后只进行最终根计算的乘法也是一种更好的性能方法。

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

Stef Graillat,"Accurate Floating-Point Product and Exponentiation",IEEE 计算机交易,卷。 58,第 7 期,2009 年 7 月,第 994-1000 页 (online)

在硬件中提供 FMA(融合乘加)运算的系统上,可以特别有效地计算此补偿乘积。所有常见的现代处理器架构(包括 CPU 和 GPU)都是这种情况。 C/C++ 通过标准数学函数 fma()fmaf().

提供对此的便捷访问

更新:提问者在评论中澄清说,下溢的风险迫在眉睫,因为 8 个因素在 [ 10-6, 10-1]。 @Yves Daoust 在评论中提到的一种可能的解决方法是将因子分成尾数和指数并分别累加。这是否可行取决于浮点环境。虽然 C 和 C++ 提供了执行此拆分的标准函数 frexp(),但此函数可能不是很快。