空间平均计算有限

时间:2013-04-19 23:20:53

标签: algorithm math big-o

假设我有N个整数,其中N可以变大,但每个int保证在0和某个上限M之间,其中M很容易适合有符号的32位字段。

如果我想计算这些N个整数的平均值,我不能总是在同一个有符号的32位空间中对它们进行求和并将它们全部除以 - 如果N太大,分子就有溢出的风险。这个问题的一个解决方案是仅使用64位字段进行计算,以保持较大的N,但此解决方案不能扩展 - 如果M是一个大的64位整数,则会出现同样的问题。

有没有人知道可以计算同一位空间中正整数列表的平均值的算法(最好是O(N))?没有做一些便宜的事情,比如使用两个整数来模拟一个更大的整数。

2 个答案:

答案 0 :(得分:5)

假设你最初知道M,你可以保留两个变量,一个是到目前为止的答案除以M,另一个是余数。

例如,在C ++中:

int ans = 0, remainder = 0;
for (int i=0;i<N;i++) {
  remainder += input[i]; // update remainder so far
  ans += remainder/N; // move what we can from remainder into ans
  remainder%=N; // calculate what's left of remainder
}

在循环结束时,答案在ans中找到,余数在remainder中(如果您需要除截断之外的舍入方法)。

此示例适用于最大输入数M + N适合32位int。

请注意,这应该适用于正整数和负整数,因为在C ++中,/运算符是除法运算符,而%实际上是余数运算符(实际上不是模运算符)。 / p>

答案 1 :(得分:1)

您可以计算出移动平均线。如果您有AN元素的平均值,并且添加了另一个元素E,则新的平均值为(A*N+E)/(N+1)。通过除以加法的分配性质,这相当于(A*N)/(N+1) + E/(N+1)。但是如果A*N溢出,您可以使用乘法和除法的关联属性,您可以将第一项转换为A*(N/N+1)

所以算法是:

n = 0
avg = 0
for each i in list
  avg = avg*(n/(n+1)) + i/(n+1)
  n = n+1