假设我们有一长串的双打,比如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();
}
当数字很小时,这可能会失去精确度。
是否有任何故障安全方法来计算浮点数的简单平均值?我们赞赏只使用标准库的解决方案。
答案 0 :(得分:3)
如果你想从双打中挤出更多的精确度,你可以使用 Kahan summation最后按元素数划分。然而,我知道没有Kahan求和的标准库实现。
一种简单,标准的方式(几乎像作弊)当然是使用长双精度计算,基本上使用你的第一个实现,只将结果转换回双精度。
答案 1 :(得分:1)
减少精度损失的一种方法是对双打进行排序,然后按排序顺序将它们加在一起,从最小值开始,然后在最后将最终总和除以双精度数。
因此,您需要的工具是std::sort
和std::accumulate
以及普通的旧版/
。
答案 2 :(得分:1)
所谓天真的方式并不天真。数据的含义是什么,以及您测量这些值的准确程度如何?除非答案是非常不寻常的,否则使用双精度的简单方法就可以了。但是浮动装置对于一般用途来说有点不足。
如果先添加小的绝对值,可能会获得额外的精度。这需要一种排序。如果数据都高于某个阈值,减去最小值也可能会给你另一个位。
您还可以存储部分总数和部分均值,并在每个阶段检查处理的部分均值*数是否在部分总数的某个容差范围内。这不会给你任何额外的准确性,但它会告诉你fpu是否太不准确了。
您也可以使用long double,甚至编写自己的扩展精度浮点库(或使用其他人)。然而,解决方案变得越来越英雄。