如何计算双精度的平均值,以便总误差最小?

时间:2017-05-20 09:19:26

标签: c++ floating-point

假设我们有一长串的双打,比如N == 1000000

array<double, N> arr;

计算平均值有两种天真的方法。首先

double result = 0;
for (double x : arr) {
    result += x;
}
result /= arr.size();

当值的总和非常大时,这可能是不准确的。浮点数会失去精度。

另一种方法是:

double result = 0;
for (double x : arr) {
    result += x / arr.size();
}

当数字很小时,这可能会失去精确度。

是否有任何故障安全方法来计算浮点数的简单平均值?我们赞赏只使用标准库的解决方案。

3 个答案:

答案 0 :(得分:3)

如果你想从双打中挤出更多的精确度,你可以使用 Kahan summation最后按元素数划分。然而,我知道没有Kahan求和的标准库实现。

一种简单,标准的方式(几乎像作弊)当然是使用长双精度计算,基本上使用你的第一个实现,只将结果转换回双精度。

答案 1 :(得分:1)

减少精度损失的一种方法是对双打进行排序,然后按排序顺序将它们加在一起,从最小值开始,然后在最后将最终总和除以双精度数。

因此,您需要的工具是std::sortstd::accumulate以及普通的旧版/

答案 2 :(得分:1)

所谓天真的方式并不天真。数据的含义是什么,以及您测量这些值的准确程度如何?除非答案是非常不寻常的,否则使用双精度的简单方法就可以了。但是浮动装置对于一般用途来说有点不足。

如果先添加小的绝对值,可能会获得额外的精度。这需要一种排序。如果数据都高于某个阈值,减去最小值也可能会给你另一个位。

您还可以存储部分总数和部分均值,并在每个阶段检查处理的部分均值*数是否在部分总数的某个容差范围内。这不会给你任何额外的准确性,但它会告诉你fpu是否太不准确了。

您也可以使用long double,甚至编写自己的扩展精度浮点库(或使用其他人)。然而,解决方案变得越来越英雄。