Floating point 浮点值的数值稳定运行平均值

Floating point 浮点值的数值稳定运行平均值,floating-point,numerical-methods,Floating Point,Numerical Methods,使用32位浮点值,计算平均值的最佳数值最精确方法是什么?如果开始计算时,我还不知道在下面的示例中,我只需迭代一个向量,就可以知道coult,但让我们假设我只知道最后的元素计数 例如,我可以这样做 float result = 0.f; for(float num: numbers) { result += num; } num /= numbers.size(); 但随着结果的增大,精度也随之增大。对于较小的值,在某一点上结果+=num;不会再改变结果了 我可以 float resul

使用32位浮点值,计算平均值的最佳数值最精确方法是什么?如果开始计算时,我还不知道在下面的示例中,我只需迭代一个向量,就可以知道coult,但让我们假设我只知道最后的元素计数

例如,我可以这样做

float result = 0.f;
for(float num: numbers) {
    result += num;
}
num /= numbers.size();
但随着结果的增大,精度也随之增大。对于较小的值,在某一点上结果+=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);
}
但我似乎会用一个累加的错误来得出这样的结果


有没有更好的方法不使用64位双精度运算?

对于这类问题,最著名的方法是Kahan求和法。请参见此处:。假设总和仍然可以表示为一个单精度浮点,则在末尾进行直接除法以找到平均值


另请参阅此答案以进行一些额外的讨论,其要求大致相同:

您希望number.size的大小大致为多少?@njuffa数千个sif number.size是2的幂,然后result=result+numbers[i]*numbers.size-1/numbers.size;至少分区不会导致精度损失。请注意,发布的代码不是运行平均值。IAC,解决现实世界问题的最佳答案考虑到您的实际应用。用户1282931,发布您的用例的更多详细信息将帮助您获得更相关的答案。这是一种已知的方法,而不是最著名的方法。对IEEE-754二进制64数字求和的最佳数值方法是保持2098位的数组,并将每个值添加到适当的位置。这没有错误,因为二进制64格式仅跨越2098位2**1023到2**-1074。提高性能的最佳方法是不执行任何操作、不维护任何数据并返回零。每件事都是一种权衡。卡汉代表着总数。然而,如果我对总和不感兴趣,而只对平均值感兴趣,我认为这是一个不同的用例,因为平均值通常比平均值小得多sum@EricPostpischil说得好!但OP的措辞表明,她/他不想使用64位双打;因此,我假设2098超出了他们的承受能力。@alias下面的方法在没有明确形成总和的情况下工作得足够好,我同意这一总和对于OP指定的几千个输入是最好的:平均值=0.0f;对于int i=0;i