【问题变了吗?也许我只看了开头。我已更新/编辑以提供更好的答复:]
我知道没有完美的解决方案(在不断的记忆中),但我可以提供各种方法。
首先,对于基本计算,您只需要所有值sum_x
的总和 ( )、它们的平方和 ( sum_x2
) 和总计数 ( n
)。然后:
mean = sum_x / n
stdev = sqrt( sum_x2/n - mean^2 )
并且所有这些值 ( sum_x
, sum_x2
, n
) 都可以从流中更新。
问题(如您所说)是处理溢出和/或有限的精度。如果您考虑浮点何时sum_x2
如此之大以至于内部表示不包括单个平方值的大小值,您可以看到这一点。
避免该问题的一种简单方法是使用精确算术,但这会越来越慢(并且还使用 O(log(n)) 内存)。
另一种可以提供帮助的方法是规范化值 - 如果您知道值通常是X
那么您可以进行计算x - X
,使总和更小(显然您然后添加X
到平均值!)。这有助于推迟精度损失点(并且可以/应该与此处的任何其他方法结合使用 - 例如,在分箱时,您可以使用前一个箱的平均值)。有关如何逐步执行此操作,请参阅此算法(knuth 的方法) 。
如果您不介意(小常数因子)O(n)内存成本,您可以重新启动每个N
值(例如百万 - 更聪明的方法仍然是通过检测精度何时过低来适应此值),存储先前的平均值和标准差和然后结合最终结果(因此您的平均值是最近运行总数和旧分箱值的适当加权值)。
分箱方法可能可以推广到多个级别(您开始分箱)并且会减少到 O(log(n)) 内存使用,但我还没有制定出细节。
最后,一个更实际的解决方案可能是对 1000 个值执行初始方法,然后并行开始新的求和。您可以显示两者的加权平均值,然后在另外 1000 个值之后,删除旧的总和(在逐渐减少它们的权重之后)并开始一个新的集合。所以你总是有两组总和,并显示它们之间的加权平均值,这给出了反映最后 1000 个值的连续数据(仅)。在某些情况下,这已经足够好了,我想(这不是一个精确的值,因为它仅适用于“最近的”数据,但它是平滑且具有代表性的,并且使用了固定数量的内存)。
ps,后来我发生了一些事情-实际上,无论如何“永远”这样做并没有多大意义,因为您将到达一个值绝对由旧数据主导的地步。最好使用“运行均值”来减轻旧值的权重。参见例如https://en.wikipedia.org/wiki/Moving_average - 但是,我不知道标准开发的常见等价物。