2017-02-19 53 views
1

我在一个读取传感器测量的约束系统中嵌入了一个C程序。我想从某个事件发生的时间起计算最近N个传感器读数期间的运行平均值。我希望计算仅使用整数运算(无浮点)。此外,我没有足够的存储空间来保存所有N个读数,所以我想创建一个运行平均总数,并在每次获得新读数时增加总数。我已经看到近似这样的一个公式是使用只有整数算术计算N个整数的平均值,并且不保留N个值

avg = ((avg * (n-1)) + currentReading)/n; 

当我编写和测试这一点,但计算出的平均值总是小于如果我添加所有的N个读数,并除以N如何提高呢?

+1

哪里是你的问题吗? –

+0

你有什么问题与你的尝试? –

回答

1

你不能得到你想要什么,除非你把过去的N个样本,但你可以用它近似:

avg = ((avg * (n-1)) + currentReading + (n/2))/n; 

这个权重当前读数有1/N的平均意义。

+0

该解决方案每个值使用1个整数除法。整数除法是一个截断操作,因此在许多值上平均值将低于精确计算值。我认为,如果您将分部修改为舍入整数部分,则答案将接近实际的平均值,而不是很多值。 –

+0

您可以在分割前添加N/2。 – stark

+0

将您的建议添加到代码 – stark

1

只需沿着值的数量保持运行总数 - 需要两个整数。简单的总和(或任何你想要的)。

+0

这不会计算最后'N'个样本读数的运行平均值。 – chqrlie

0

OP的代码已经接近但会受益于四舍五入的划分而不是标准的整数划分。所以添加一个偏见。偏差取决于操作数的符号。

// avg = ((avg * (n-1)) + currentReading)/n; 
avg = (avg * (n-1)) + currentReading + bias)/n; 

第二个问题是范围之一:(avg * (n-1)) + currentReading容易溢出。求助于更广泛的数学的最简单的解决方案。使用更宽的类型

// Example, depends on system 
// avg * (n-1)) + currentReading 
1uLL * avg * (n-1)) + currentReading 

一起把这个:

// avg = ((avg * (n-1)) + currentReading)/n; 
int avg, currentReading; 
int n; // n > 0 
int2x numerator; // int2x some type 2x wide as int, maybe long long 

numerator = (int2x)avg * (n-1) + currentReading; // Wider math 
int bias = n/2; 
if (numerator < 0) bias = -bias; 
numerator += bias; 

avg = (int) (numerator/n);