【问题标题】:Averaging increasing number of variables平均越来越多的变量
【发布时间】:2010-06-02 08:37:39
【问题描述】:

我必须报告传入数字的平均值,如果不使用某种数据结构来跟踪所有值,然后通过将它们相加并除以值的数量来计算平均值,我怎么能做到这一点?

【问题讨论】:

标签: c# numbers average


【解决方案1】:

只需不断计算总和以及您收到多少个数字,这就是计算平均值所需的全部内容。

【讨论】:

    【解决方案2】:

    如果我没记错的话,也可以这样计算avg(n+1)

    avg(n+1) = (a[1]+ ... + a[n+1]) / (n+1) = 
             = (a[1]+ ... + a[n])/(n+1)   +   a[n+1]/(n+1) = 
             = (n(a[1]+ ... + a[n])/n) / (n+1) + a[n+1]/(n+1) =
             = n*avg(n) / (n+1) + a[n+1]/(n+1) = 
    
             = n/(n+1) * avg(n) + a[n+1]/(n+1)
    

    所以将旧的平均值乘以n/(n+1),然后加上新元素除以n+1。根据n 的高度以及您的值有多大,这可以减少舍入误差...

    编辑:当然你必须使用浮点数计算n/(n+1),否则它总是会呈现 0...

    【讨论】:

      【解决方案3】:

      如果您有数字 a[1] a[2] ... a[n] 并且您知道它们的平均值是 avg(n) = (a[1] + ... + a[n]) / n,那么当您获得另一个数字 a[n + 1] 时,您可以这样做:

      avg(n + 1) = (avg(n) * n + a[n + 1]) / (n + 1)

      一些浮点错误是不可避免的,但您应该对此进行测试,看看它是否足够好。

      为了避免溢出,你可以先做除法:

      avg(n + 1) = (avg(n) / (n + 1)) * n + (a[n + 1] / (n + 1))

      【讨论】:

        【解决方案4】:

        保持当前的总和和计数。更新每个传入号码。

        avg = sum / count.
        

        【讨论】:

        • 这可能是一个简单的解决方案,但由于浮点数的精度有限,我不能使用这种简单的方法 - 我每秒有大量的数字传入,所以总和会变得​​非常大并且有些浮动会出现点错误...
        • @Oscar:那么,您应该在问题中指定此限制。就目前而言,您的问题并不是很复杂!
        • @Dan:这是一个众所周知的浮点数平均问题,当你对大量数字求和时,几乎总是应该考虑这个问题。
        • 你也可以保持当前的平均值和计数,并做 new_avg = (old_avg*old_count + incoming) / (old_count + 1)
        • @ob1:所以你做的完全一样,只是增加了一个乘法。
        【解决方案5】:

        您不需要跟踪总和,只需计数器:

        class Averager {
           float currentAverage;
           size_t count;
           float addData (float value) {
               this->currentAverage += (value - this->currentAverage) / ++count;
               return this->currentAverage;
           }
        }
        

        来自-> prevent long running averaging from overflow?

        【讨论】: