关于不定长数组(大数组)求平均值的算法!解决方法

关于不定长数组(大数组)求平均值的算法!!!!
应用环境是工作某个工作状态时,会不断产生一些数,这些数的个数是不确定的,和工作时间有关系,时间长数的数目就多些,时间短数的数目就少点!根据需要要求这些数的平均值。即是工作这段时间的产生这些数的平均值!基本上一秒钟会产生1~2个数,一般工作时间是1小时到8小时不等!
  现在我的目的是想求这么多数的平均值,跟应用有关系!目的是找到个即节省资源,又不至于结果偏差太大的方法!!不知道如何处理这类东西的!

------解决方案--------------------
没完全看明白楼主的需求,
节省资源的话只能用时间换空间了
楼主说的数是什么类型的数?应该是实数吧?
2 * 3600 * 8也不算大,一个32位的int就可以了
比如:
楼主可以维护一个cnt记录当前数据的个数,evr记录当前的平均值
然后每增减一个新数据val时,更新这个cnt和evr的值即可
erv += ((val - erv) / ++cnt);
------解决方案--------------------
楼主的如果每秒钟得到数字有个范围的话(比如0到9之间的数字),应该还是蛮好解决的。比如,5秒钟内得到的数字是:
2
2
5
3
3
那么可以先创建一个数组a[10],如果得到的数字是2,那么就a[2]++,如果得到的数字是5,那么就a[5]++..用这种办法记录数字出现的次数。需要计算平均值的时候,就可以这么做:
数字 * 数字出现的次数 / 总的数字出现次数。以上面给出的数字为例,就可以这么写:
2 * 2 / 5 + 3 * 2 / 5 + 5 * 1 / 5 = 3

这样可以避免大数的运算。但前提条件是要知道每次得到数据的范围,才会比较方便。

仅提供一个思路,供楼主参考。
------解决方案--------------------

int main()
{
    int cnt = 0;
    double evr = 0;
    int i;

    double d[] = {1234.5678, 1.23, 454.42, 178674.5843, 343.99};

    //模拟,每产生一个数就更新这个cnt和evr
    for (i = 0; i < sizeof(d) / sizeof(d[0]); ++i)
    {
        evr = evr + ((d[i] - evr) / ++cnt);//防止相加导致溢出
    }
    cout<<evr<<endl;
    
system("pause");
return 0;
}

------解决方案--------------------
要不就实时更新average和count
average= average * count / (count + 1) + a / (count + 1);
count++;
------解决方案--------------------
引用:
总体看了下,思路大概是先取一定量的平均值,这样可以避免大数的相加,sum+=data;如果加到最后sum肯定很大,会溢出!我的那些类型的数据其实是三相电压量(380左右),三相电流量(10-50),频率量(50左右),线电压等量。
我觉的要么避免出现大数,隔段时间取和取下平均值,但后面的操作比较复杂,按照6楼说法,满100保存下,1-100前数据小可以取值,然后怎么处理,我不知道要保存多少这样的……

用long还不会溢出吧?
------解决方案--------------------
照你说的sum最终的值依然在int32的范围之内,根本就不涉及到大数乘除法。直接计算就是了。
------解决方案--------------------
记录个数(N)和平均数(A),每产生一个新数(K)计算一次:A=((A*N)+K)/(N+1),这样可以防止溢出吧。
------解决方案--------------------
引用:
总体看了下,思路大概是先取一定量的平均值,这样可以避免大数的相加,sum+=data;如果加到最后sum肯定很大,会溢出!我的那些类型的数据其实是三相电压量(380左右),三相电流量(10-50),频率量(50左右),线电压等量。
我觉的要么避免出现大数,隔段时间取和取下平均值,但后面的操作比较复杂,按照6楼说法,满100保存下,1-100前数据小可以取值,然后怎么处理,我不知道要保存多少这样的……



如果产生的数都在380左右
可以这样
//初始值
remain = 0;
count = 0;
//开始产生数
num//产生的数
++count;//记录数据的个数
remain = remain + 380 - num;
//数据产生完后
average = 380 + remain / count;

------解决方案--------------------
引用:
引用:

照你说的sum最终的值依然在int32的范围之内,根本就不涉及到大数乘除法。直接计算就是了。

这样算算也是啊,但既然问题是问大数的,不知道如果出现大数的怎么处理?

按照每次取一定量来求平均值的做法是可以。
假设每次取100个值计算平均值,第n+1次平均值可以这么算:
f(n+1)=[f(n)*n+(a(100*n+1)+a(100n*n+2)+...+a(100*n+n))/100]/(n+1)
------解决方案--------------------
每次计算平均值,新的数产生以后,计算与平均值的差值,按总个数加权,更新平均值。这样就不存在超大的和可能导致溢出,或者每次计算量过大的问题了吧。
例如,220, 210,计算平均215
产生200,计算差值为15,加权总个数3个,15/3=5,215-5=210,为新的平均值。
------解决方案--------------------
设x为已有数据的平均数,n为已有数据的个数,新的数据为y
那么就是
(x * n + y)/(n+1) =( x * (n+1)  - x + y )/(n+1) = x + (y-x)/(n+1);

x + (y-x)/(n+1);这样就简单了。用double 应该问题不大。