任意多个数字求平均数
我们在进行数据的平均计算时,通常采用先求和再除以数量进行平均的方法。但是这个方法有个隐患,就是如果进行平均的数字数量很多,求和时难免要溢出,导致错误结果。
为了解决这个问题,我们可以这样做:
如果我们有了n个数字的平均数avg,当第n+1个数字num想要参与平均,那么在新的平均数中,avg要占n/n+1,而num则占1/n+1。所以n+1个数字的平均数为avg/(n+1)*n+num/(n+1)。
数学证明:设A为n个数字的平均值,即
A=M1+M2+..+Mnn
A=\frac{M_{1}+M_{2}+..+M_{n}}{n}
A=nM1+M2+..+MnB为n+1个数字的平均值
B=M1+M2+..+Mn+Mn+1n+1
B=\frac{M_{1}+M_{2}+..+M_{n}+M_{n+1}}{n+1}
B=n+1M1+M2+..+Mn+Mn+1我们对第二个公式进行变换,得
B=M1+M2+..+Mnn+1+Mn+1n+1
B=\frac{M_{1}+M_{2}+..+M_{n}}{n+1}+\frac{M_{n+1}}{n+1}
B=n+1M1+M2+..+Mn+n+1Mn+1=M1+M2+..+Mnn+1∗nn+Mn+1n+1
=\frac{M_{1}+M_{2}+..+M_{n}}{n+1}*\frac{n}{n}+\frac{M_{n+1}}{n+1}
=n+1M1+M2+..+Mn∗nn+n+1Mn+1=M1+M2+..+Mnn∗nn+1+Mn+1n+1
=\frac{M_{1}+M_{2}+..+M_{n}}{n}*\frac{n}{n+1}+\frac{M_{n+1}}{n+1}
=nM1+M2+..+Mn∗n+1n+n+1Mn+1=A∗nn+1+Mn+1n+1
=A*\frac{n}{n+1}+\frac{M_{n+1}}{n+1}
=A∗n+1n+n+1Mn+1
所以,只要我们知道了前n个数字的平均数,再知道参与平均的数字数量,那么再有更多的数字要参与平均,也不需要先求和导致溢出错误。
计算平均数的代码很简单,只有一行,其他都是测试用代码。
要注意的是,先做除法,再做乘法,可以避免乘法带来的溢出可能。
#include <stdio.h>
#include <stdlib.h>
float average(int count, float avg, int num);
int main()
{
int i;
int count= 0;
float avg = 0;
for(i = 1; i <=100; i++) {
avg = average(count, avg, i);
count++;
}
printf("The avg is %f.\n", avg);
}
// 用于计算一系列数字的平均数计算函数,优点是不用
// 计算求和,避免求和时计算溢出。
// 函数返回值为平均值计算结果,
// 输入参数中
// count为到目前为止参与平均的数字数量,
// avg为之前所有输入数字的平均数
// num为新的一个参与平均计算的数字 num为浮点数也是可以的
float average(int count, float avg, int num)
{
return (avg/(count+1)*count + num/(count+1.0));
}