用于计算扩展数据阵列的平均数的公式

时间:2013-05-23 21:54:09

标签: c# rate

说,如果我有最后一组数字,请说:

{1, 5, 7, 2}

他们的平均值是:

(1 + 5 + 7 + 2) / 4;   //Or, sum of all elements, divided by their number

但是如果我的阵列不断增长并且我需要知道当时尚未知道完整阵列的当前实例的当前平均数。你是如何计算的?

说,就像我试图显示当前的数据传输速率一样。

8 个答案:

答案 0 :(得分:3)

我会采用一种简单的方法来获得具有恒定空间复杂度的running total(累积)(1)。并根据avg的请求,返回running total/total number of item的结果。没有延长的时间复杂度,因为我们之后不迭代数组来查找累积和。

答案 1 :(得分:2)

每次获得新值时,都需要更新您的总和和数量,并在需要将它们显示给用户时将它们分开。

对于数据传输速率,这是有问题的方法。考虑一下您开始高带宽传输然后连接中断的情况,通过简单的平均值,您的UI可能需要很长时间来反映当前传输速率为0。 使用加权移动平均线是一种让您的UI看起来更具响应性的快速方法。

最简单的实现方法是定期(比如每5秒)对传输速率进行采样,并使用以下方法计算您的费率:

 float weight = 2.0; //you are going to want to tweak this to get the right balance between "responsive" and "noisy"

 void UpdateAverage(float newValue)
 {
    this.Average = (this.Average + (newValue*weight))/(weight+1)
 }

答案 2 :(得分:2)

我知道我在这里参加晚会但是我在2000年解决了类似的问题,当时我正在创建一个自适应负载均衡器。标准平均值有两个问题,两者都在答案中提到:

     
  1. 溢出情况
  2. - 保持运行总计将导致溢出  
  3. 重新计算平均值
  4. - 通常,您必须为每个样本执行此操作

    所以你可以把正常的平均计算变成一个数学民间所谓的'递归关系',这意味着你存储以前的平均值,然后用来计算新的平均值(类似于Yaur的答案,我必须同意和艾哈迈德一样,我看不出它被投票了。我在当天在Delphi中写了原文,所以我最近在.NET中再次做了同样的事情,并将它与计算连续平均值的标准过程进行了比较,因为项目列表越来越大。

    不想自我推销(我发布链接只是为了保存我的打字手指),你可以找到理论处理,代数,比较实验的结果以及它如何解决问题:

    http://goadingtheitgeek.blogspot.co.uk/2014/05/blast-from-past.html

    我希望你觉得它很有用。

答案 3 :(得分:1)

我敢打赌,你想要快速的东西,否则你已经得到了答案。按已有数组的长度求和已有的所有数字。这非常简单。

然而,有时您无法知道阵列是否有界,它可能是无限的,例如来自麦克风的数据。在这种情况下,移动平均线的建议很好,这意味着您必须从数组中获取最后的x值并仅计算这些值的平均值。无论您有x值还是1000x值,计算结果所需的算法和时间都保持不变。

编辑:

x vs 1000x来自算法的复杂性。假设您将5个数字相加,即5个操作,然后除以5,另一个操作共计6个(为了示例,我们假设它们都占用相同的计算机时间,但实际上除法很慢与添加相比)。如果您使用相同的代码,但使用1000个数字,则执行1001次操作,这将比第一种情况花费更多时间!

对于“移动平均线”,您总是需要固定数量的数字,因此无论您有5个还是1000个数字,您的算法都需要一定的时间来执行。

移动平均线只是一种奇特的措辞,表示你不会在阵列中使用相同的数字。想象一下以下数组:

int x = { 1, 4, 6, 3, 1 };
int arrayLength = 5;

然后这个数组的平均值为

int runningTotal = 0;
for(int i = 0; i < arrayLength; i++)
{
   runningTotal += x[i];
}
double average = runningTotal / arrayLength

3个值的移动平均值

int movingLength = 3;
int runningTotal = 0;
for(int i = 0; i < movingLength; i++)
{
   runningTotal += x[arrayLength - i - 1];
}
double average = runningTotal / movingLength;

因此,当数组增长时,数组中的第一个值不是计算的一部分。

答案 4 :(得分:1)

您正在寻找移动平均线:

    static void Main(string[] args) {
        var nums = Enumerable.Range(1, 5).Select(n => (double)n);
        nums = nums.Concat(nums.Reverse());

        var sma3 = SMA(3);
        var sma5 = SMA(5);

        foreach (var n in nums) {
            Console.WriteLine("{0}    (sma3) {1,-16} (sma5) {2,-16}", n, sma3(n), sma5(n));
        }
    }

    static Func<double, double> SMA(int p) {
        Queue<double> s = new Queue<double>(p);
        return (x) => {
            if (s.Count >= p) {
                s.Dequeue();
            }
            s.Enqueue(x);
            return s.Average();
        };
    }

来源:http://rosettacode.org/wiki/Averages/Simple_moving_average#C.23

答案 5 :(得分:0)

假设您想要移动平均线..

您需要在上次计算平均值时跟踪元素的当前总和。

如果你的阵列就是这个......

Array = {1, 5, 7, 2}
Sum = 1 + 5 + 7 + 2 = 15
Number of elements = 4
Average = Sum / Number of elements = 3.75

你添加了几个元素,你的数组看起来像这样......

Array = {1, 5, 7, 2, 10, 6}

假设你的实际阵列要大得多......要重新计算平均值..

Sum = ([previous sum] + [sum of new elements]) / [number of elements]
Number of elements = 6
Average = ((15 * 4) + 10 + 6) / 6 = 5.1666667

修改:如果您关注精度和尺寸,请查看BigInteger

答案 6 :(得分:0)

如果平均缓冲区长度可以改变我的旧程序就是这样。

namespace WindowsFormsApplication1
{
  public partial class ComTester : Form
  {
    public int []sAvgArr=new int [251];
    public int sAvgAdr,sAvgCnt;

    private void Calc_Values(object sender, int v)//v is value
    {
        int n = AverageLength;
        if (n > 250) n = 250;//average buffer maksimum
        if (n > 0)
        {
            sAvgArr[sAvgAdr] = v;
            sAvgAdr += 1;
            sAvgCnt += 1;
            if (n <= sAvgAdr) sAvgAdr = 0;
            if (n <= sAvgCnt) sAvgCnt = n;
            n = sAvgCnt;
            int f = 0, l = 0; ;
            for (l = 0; l < n; l += 1)
                f += sAvgArr[l];
            f = f / sAvgCnt;
            sAvgVal = f;
        }
        else 
        {
            sAvgVal=v;
        }
    }
  }
}

答案 7 :(得分:-2)

using System;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            int  n = 3 , x , sum = 0 ;
            double ave;

            for (int i = 0; i < n; i++ )
            {
                Console.WriteLine("enter the number:");
                x = Convert.ToInt16(Console.ReadLine());
                sum += x;
            }

            ave = (double)(sum) / 3;
            Console.WriteLine("average:");
            Console.WriteLine( ave );
            Console.ReadLine();
        }
    }
}