首页 > 解决方案 > 浮点值的数值稳定运行平均值

问题描述

使用 32 位浮点值,如果 - 开始计算时 - 我还不知道我将拥有多少个值(在以下示例中我只是迭代一个向量,那么计算平均值的最佳(数值上最准确)的方法是什么?我会知道库尔特,但假设我最终只知道元素计数)?

例如,我可以做

float result = 0.f;
for(float num: numbers) {
    result += num;
}
num /= numbers.size();

但随着结果变大,精度也会变大。使用较小的值,在某些时候result += num;实际上不会再改变结果。

我可以

float result = numbers[0]
for(int i=1, i<numbers.size(); i++) {
    float frac = (i/float(i+1));
    result = result * frac + numbers[i] * (1.0f-frac);
}

但似乎我会以这种方式应用累积错误。

有没有更好的方法而不去 64bit double?

标签: floating-pointnumerical-methods

解决方案


这类问题最著名的方法是 Kahan Summation。见这里:https ://en.wikipedia.org/wiki/Kahan_summation_algorithm 。假设总和仍然可以表示为单精度浮点数,请在最后进行直除以找到平均值。

另请参阅此答案以进行一些额外的讨论,该讨论要求或多或少相同:如何计算双打的平均值,以使总误差最小?


推荐阅读