C 寻找平均值的更好算法
我正在练习一本编程书,一本关于C的书。该练习建议,要找到一组数字的平均值,算法:C 寻找平均值的更好算法,c,algorithm,C,Algorithm,我正在练习一本编程书,一本关于C的书。该练习建议,要找到一组数字的平均值,算法: avg += (x - avg) / i; 优于: sum += x; avg = sum / i; “x”是用于存储输入数字的变量。它还建议除了防止溢出外,第一种算法确实比第二种算法有其他一些好处,有人能帮我吗?谢谢 更好的方法是,它计算一个运行平均值,也就是说,你不需要提前知道所有的数字。你可以边走边计算,或者在数字可用时计算 sum += x; avg = sum / i; 在上面的代码中,假设我们的数
avg += (x - avg) / i;
优于:
sum += x;
avg = sum / i;
“x”是用于存储输入数字的变量。它还建议除了防止溢出外,第一种算法确实比第二种算法有其他一些好处,有人能帮我吗?谢谢 更好的方法是,它计算一个运行平均值,也就是说,你不需要提前知道所有的数字。你可以边走边计算,或者在数字可用时计算
sum += x;
avg = sum / i;
在上面的代码中,假设我们的数字为1000020000,…即包含大量数字的数字,则总和中的值可能会超过其最大值,而在第一个代码中,情况并非如此,因为总和在存储之前总是除以元素的个数
虽然由于编程语言中存在大量数据类型,这可能不是问题
专家说“根据您的应用程序和需求使用数据类型。”后一种算法比前一种算法更快,因为您必须执行n个操作(实际上,后者需要执行2*n个操作)。但第一种方法确实可以防止溢出。例如,如果你有1000个数字:4000000×250, 1500000×500, 2000000 *500,所有整数的总和将是2’70.0.000,000,但是C++ INT数据类型的上限是2147483647。所以,我们正在处理一个溢出问题。但是如果你执行第一个算法,那么你就能够处理这个问题
因此,如果可能发生溢出,我建议您使用第一个算法,否则它只会添加额外的操作。如果您决定无论如何使用第一个,那么我建议您使用范围更大的类型。我假设我们在这里讨论的是浮点算术(否则“更好”的平均值将非常糟糕) 在第二种方法中,中间结果(
sum
)将趋向于无边界增长,这意味着您最终将失去低端精度。在第一种方法中,中间结果应该与输入数据保持大致相似的大小(假设输入没有很大的动态范围)。这意味着它将更好地保持精度
然而,我可以想象,随着I
变得越来越大,(x-avg)/I
的值将变得越来越不准确(相对而言)。因此它也有它的缺点。我更喜欢第二种方法(循环求和,最后除法),并且识别第二种方法的速度比第一种快得多
性能差异(如果有的话)无关紧要
而且,如果一个值的总和溢出了足够大的数据类型,您可能会遇到比计算平均值更多的问题。好的,答案不在于溢出总和(因为这是不可能的),而是正如Oli在“失去低端精度”中所说的那样。如果要求和的数字的平均值远大于每个数字与平均值的距离,则第二种方法将丢失尾数位。因为第一种方法只是查看相对值,所以它不会遇到这个问题 因此,任何大于(比如)6000万(对于单精度浮点)但值的变化不超过10左右的数字列表都应该显示其行为
如果使用双精度浮点,则平均值应高得多。或者delta要低得多。假设整数在一个数组中,这样计算怎么样
sum += x[i] / N; rem += x[i] % N;
avg = sum + rem/N;
如果
N
较大(0xFFFFF)且x[i]
均较小,则rem
加起来等于0xFFFF(最大整数),则可能发生溢出。Heh。我桌上正好有那本书的第一版。这是在哪一章?反论点---第二种方法,忽略溢出,可能是因为只执行了一个除法:)@pmg只是一个很棒的注释。如果是溢出,我们为什么要选择I'st方法。无法从这里发布的答案中清除。@pmg可能我遗漏了什么,但是第一个方法如何执行两个划分呢?第一个方法有一个环绕+=
表达式的循环;第二个表达式还有一个环绕+=
表达式的循环。因此,在第一个迭代中,每个迭代都有一个除法,但第二个迭代只有一个除法。使用第一种方法的原因与数值稳定性和避免溢出有关。请参阅上的讨论,尤其是Wikipedia页面(以及相关的,可能更相关的页面)。OP上说“除了防止溢出之外”,您将能够在恒定时间内计算每个增量平均值,而不是O(N),谢谢"在本练习中,您将继续上一个练习中所做的工作。如果您从包含一些普通数字的文件中获取输入,运行平均值更好的程序,那么第一个算法和第二个算法似乎会产生相同的答案。找到一种情况并非如此。即,演示实验你能告诉我哪种情况会发生这种情况吗?-1:他们都能计算出运行平均值。+1你能解释一下“失去低端精度”吗"@算法:考虑浮点表示的结构;尾数和指数。尾数代表精度,即有效数字,并且有固定数目。随着你的数字越来越大,指数将开始增加,这意味着你的有效数字被乞求。在我看来,(x-avg)/I
的问题只是部分由I
变大引起的。如果许多数字是CLO,那么(x-avg)
部分本身也是一个问题