【问题标题】:Average for moving items [closed]移动项目的平均值[关闭]
【发布时间】:2013-07-05 07:03:14
【问题描述】:

我需要制定一个有效的算法来移动整数。

例如,平均 100 个项目。 因此,随着 100 个数字的到来,1..100 个数字的平均值.. 由于 101 数字平均为 2..101.. 由于 102 数字平均为 3..102..

我想到了一个解决方案,但我想不出这样可以存储最少的数字(在病房之后,我必须在微处理器中做,但首先,在 C/C++ 中高效):

第 1 步:存储 1..100 的数字并取平均值 第 2 步:将 1 替换为 101,取平均值:101,2,3...100 第 3 步:将 2 替换为 102,取平均值:101,102,3,4...100

但效率不高,因为我还需要使用较少的除法运算符。

谁能帮帮我。

【问题讨论】:

  • 谷歌移动平均
  • 如果您存储上一步的总和(而不是平均值),则无需完全重新计算所有 100 个数字的平均值。您只需从总和中减去一个值并添加新值,然后将总和除以 100。不过,这并不会减少除数。
  • 需要少用除法运算符吗?或者您只是想提出这样的要求,让问题变得更难,解决方案“更快”?
  • “微处理器”是可以执行完整指令集的任何微芯片。如果您的意思是“8位微控制器”,那就更具体了。但仅仅拥有某些硬件并不能证明这样的设计决策是合理的,而且“少用分工”也不是真正的工程要求。如果您需要将其限制为移位操作或其他内容,或者某些结果可能是近似的,那么请说出来。

标签: c++ c


【解决方案1】:

您的基本方法很好:使用包含 100 个元素的循环缓冲区。一个关键见解:假设您处于“将 2 替换为 102”阶段,2 为 50,而 102 为 70 - 总数将变化 +20 的差值:您只需将新总数除以 100 即可得到新的平均,没有再次将所有元素相加。

万一除法速度如此缓慢,它会对您的整体表现产生重大且有问题的差异,那么您只能尝试几件事(但要衡量一下 - 它们实际上可能会变慢取决于你的具体硬件):

【讨论】:

  • 值得注意的是,这种方法会导致浮点运算中的数值问题(将x[n] 添加到总和然后再减去x[n] 可能不会完全取消)。在整数算术中,这非常有效。
  • 另外,每次除以 100 并不考虑循环缓冲区尚未满的情况。通常这可以称为程序启动的一部分。通常可以将缓冲区大小设为 2 的幂以简化该部分。还记得在执行地板除法之前通过将缓冲区大小的一半添加到总和来四舍五入。
  • @Potatoswatter: true - 我专注于可以在缓冲区已满的稳态模式下启动一次的优化。
【解决方案2】:

进行移动平均的最简单方法是使用移动总和。将数字 n[0] 到 n[99] 相加即可开始;平均值是这个总和除以 100。对于下一个总和,减去 n[0] 并加上 n[100];再除以 100 得到平均值。

这对整数最有效,因为总和不会有任何舍入误差;使用浮点时,任何错误都会累积并随着您的进行而变得更糟。

如果您使用的是正整数,则可以通过将窗口大小设为 2 的幂来消除除法。使用 128 而不是 100 意味着您可以在总和上使用 7 的右移进行除法。

您还可以通过乘以倒数来消除除法。不是除以 100,而是乘以 1/100。如果您使用整数,您可能需要使用定点,如果您不小心,也可能会用完位。

【讨论】:

  • 所以你建议在 n[0] 到 n[99] 的平均值之后,我应该删除 n[0] 并仅在 n[0] 位置添加 n[100] 吗?我拿了一个 [100].. 的数组
  • @user2387900 我的意思是保留先前计算的总和并更改它。所以第一个总和 (sum0) 是 n[0] 到 n[99] 的总和。第二个和 (sum1) 是 sum0-n[0]+n[100]。第三个是 sum1-n[1]+n[101]。等等。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-03-22
  • 1970-01-01
  • 2014-11-29
  • 2017-09-01
  • 2015-05-03
相关资源
最近更新 更多