我在接受采访时被问到这个问题。 我被要求计算数字x1,x2,x3,... xn
的平均值class Iterator {
bool hasNext;
int getNext();
}
//所以它归结为这样:
double average (Iterator & it) {
double average = 0;
double sum = 0;
int len = 0;
while (it.hasNext == true) {
sum += it.getNext();
}
if (len > 0)
average = sum / len;
}
采访者说清单大小未知且可能非常大,因此总和可能会溢出。他问我如何解决溢出问题,我通过跟踪我们如何超过最大数量等来回答,他说了一些关于推入堆栈的事情,平均值和长度,我从来没有真正理解他的解决方案通过推动这些2变量成某种列表?有人有线索吗?
答案 0 :(得分:3)
我不知道如何使用堆栈,但在代数的帮助下,我们可以使用旧的平均值得出新平均值的公式。
我们假设您已经平均n - 1
项,并且您在oldAvg
中获得了平均值。
oldAvg =(x 1 + x 2 + .. + x n - 1 )/(n - 1)
新的平均值将由newAvg
表示:
newAvg =(x 1 + x 2 + .. + x n - 1 + x n )/ n
通过一些代数操作,我们可以使用旧平均值表示新平均值,平均项目数和下一项。
newAvg =(x 1 + x 2 + .. + x n - 1 )/ n + x n < / sub> / n
=((n - 1)/(n - 1))*(x 1 + x 2 + .. + x n - 1 < / sub>)/ n + x n / n
= oldAvg / n *(n - 1)+ x n / n
这可以在乘以n
之前除以n - 1
以避免溢出。然后你所要做的就是添加下一个项目x n ,除以n
。
第一个循环将平均值设置为等于第一个元素,但每个后续循环将使用上面的公式来推导新的平均值。
n++;
newAvg = oldAvg / n * (n - 1) + it.next() / n;
答案 1 :(得分:2)
他可能指的是您不需要所有条款来计算平均值,而是可以跟踪moving average。这可以与迄今为止考虑的术语总数一起使用。
由于总数可能太大而无法长时间存储,因此您需要使用类似BigInteger
的内容来保存总数。
答案 2 :(得分:2)
如果您进一步简化rgettman的公式,您将获得以下信息:
len++;
average = average + (it.next() - average) / len;