更好的算法找平均值

时间:2011-06-03 13:15:12

标签: c algorithm

我正在编写一本编程书 A Book on C 。练习建议找到一组数字的平均值,算法:

avg += (x - avg) / i;

优于:

sum += x;
avg = sum / i;

'x'是用于存储输入数字的变量。它还建议除了防止溢出之外,第一个算法确实比第二个algorthim有其他一些好处,任何人都可以帮助我吗?谢谢!

7 个答案:

答案 0 :(得分:9)

我假设我们在这里谈论浮点运算(否则“更好”的平均值会很糟糕)。

在第二种方法中,中间结果(sum)倾向于无限制地增长,这意味着你最终将失去低端精度。在第一种方法中,中间结果应保持与输入数据大致相似的幅度(假设您的输入没有巨大的动态范围)。这意味着它将更好地保持精度。

然而,我可以想象随着i变得越来越大,(x - avg) / i的值会变得越来越不准确(相对)。所以它也有它的缺点。

答案 1 :(得分:4)

在某种意义上它更好地计算出一个平均值,即你不需要提前拥有所有数字。您可以随时计算,也可以在数字可用时计算。

答案 2 :(得分:1)

后一种算法比前者更快,因为你必须执行n次操作(实际上,后者需要执行2 * n次操作)。但确实第一个防止溢出。例如,如果你有这组1000个数字:4000000 * 250,1500000 * 500,2000000 * 500,所有整数的总和将是2'750.000.000,但是c ++ int数据类型的上限是2,147,483,647。所以,我们正在处理这种情况下的溢出问题。但是如果你执行第一个算法,那么你就可以解决这个问题了。

所以我建议您使用第一个算法,如果它可能发生溢出,否则它只会添加额外的操作。如果您决定使用第一个,那么我建议您使用范围更大的类型。

答案 3 :(得分:1)

我喜欢第二种方法(在循环中求和并在末尾划分)更好,并且可以比第一种方法更快地识别第二种方法。

性能差异(如果有)无关紧要。

并且,如果值的总和溢出足够大的数据类型,则可能比计算平均值有更多问题。

答案 4 :(得分:1)

好的,答案不在于溢出总和(因为这被排除在外),而是正如Oli在“失去低端精度”中所说的那样。如果您求和的数字的平均值远大于每个数字与平均值的距离,则第二种方法将丢失尾数位。由于第一种方法只是查看相对值,因此不会遇到这个问题。

因此,任何大于60万的数字列表(对于单精度浮点数)但值的变化不超过10左右应该会显示行为。

如果使用双精度浮点数,则平均值应该高得多。或者三角洲低得多。

答案 5 :(得分:0)

sum += x;
avg = sum / i;

在上面的代码中假设我们将数字设置为10000,20000,...这是包含大量数字的数字,那么总和中的值可能会超过其MAX值,但总和中总和的情况并非如此。在存储之前没有元素。

虽然由于编程语言中存在大量数据类型,这可能不是问题。那么

专家说“根据您的应用和要求使用数据类型。”

答案 6 :(得分:-3)

假设整数在数组中,那么这样计算怎么样?:

sum += x[i] / N; rem += x[i] % N;
avg = sum + rem/N;

如果N很大(0xFFFFF)且x[i]都很小,那么rem加起来为0xFFFF(最大的int),那么可能会发生溢出。