如何稳健地计算平均值(平均值)?

Mar*_*dik 10 c++ algorithm floating-point

如果我们天真地计算平均值:

std::vector<double> values;
double sum = std::accumulate(begin(values), end(values), 0.0);
double mean = sum / values.size();
Run Code Online (Sandbox Code Playgroud)

并且values.size()很大,我们可能会得到不准确的结果,因为浮点数在较高范围内的分辨率较低.或者更糟糕的是,如果我理解正确,我们可以获得无限的结果.

当我们有偶数个值时,我们可以计算前半部分的平均值,然后计算第二个的平均值,并找到这两个均值的平均值.

这似乎不是一个新问题,但我很难找到资源.我觉得有更复杂的技术权衡

  • 稳健性
  • 计算复杂性
  • 难以实施

我想知道是否有人将它们总结到某个地方甚至更好,如果它们在某些图书馆中可用的话.

Jua*_*pes 8

您可以使用此处所述的在线算法.

基本上(在pythonish伪代码中):

n = 0
mean = 0

for value in data:
    n += 1
    mean += (value - mean)/n
Run Code Online (Sandbox Code Playgroud)

该算法在数值上比天真的实现更稳定.

  • @LieRyan:对`n`使用`double`.这也可以节省你的int-to-float转换. (2认同)

tmy*_*ebu 8

这里可能会发生很多愚蠢的事情.一个问题是溢出的东西.另一个例子如下: (1e100 + 1) - 1e100) == 0.另一个是刚刚累积的四舍五入.

对于大规模数据,Kahan求和处理累积很好.使用Kahan求和求和,然后除以数据的数量.

为了处理数据不佳的数据,您可以按指数(比如50个不同的桶,每个桶覆盖大约20个不同的指数)和Kahan-sum以递减的桶顺序存储数据.

当然,这都是大规模的矫枉过正,而且速度相当慢.在实践中,使用矢量指令和类似的东西有助于提高速度精度.