计算可变参数的移动平均值

我有一个整数属性,每秒更新信号强度值范围从0 – 100。

我希望能够在过去的10,25,50次测量中保持移动平均的持续测量。

什么是最有效的方法呢?

我目前正在考虑使用NSMutableArray来实现一组FIFO队列,并在每次添加一个新的队列时popup前导值,一旦该arrays具有必要的条目数量。 但是,我不确定是否有一个更有效的方法来做到这一点。

队列是正确的。 真正的效率来自于如何重新计算平均值。

它应该完成:

avg = avg + newSample/N - [queue dequeue]/N [queue enqueue:newSample] 

即新的运行平均值仅仅是旧的平均值减去您丢弃的最老的值的权重,再加上您排队的最新值的权重。

我写了一个名为MovingAverage的简单类来处理这个问题。 您可以使用要维护的周期数初始化该方法,并使用样本计数的模数来跟踪其余部分,以知道将哪个静态插槽放入其中。

用…初始化

 MovingAverage *avg5periods = [[MovingAverage alloc] initWithSize:5]; 

添加项目:

 [avg5periods addSample:1.0]; NSLog(@"1.2f",[avg5periods movingAverage]); //1.0 [avg5periods addSample:2.0]; NSLog(@"1.2f",[avg5periods movingAverage]); //1.5 [avg5periods addSample:3.0]; NSLog(@"1.2f",[avg5periods movingAverage]); //2.0 [avg5periods addSample:4.0]; NSLog(@"1.2f",[avg5periods movingAverage]); //2.5 [avg5periods addSample:5.0]; NSLog(@"1.2f",[avg5periods movingAverage]); //3.0 [avg5periods addSample:6.0]; NSLog(@"1.2f",[avg5periods movingAverage]); //4.0 

头文件:

 #import <Foundation/Foundation.h> @interface MovingAverage : NSObject { NSMutableArray *samples; int sampleCount; int averageSize; } -(id)initWithSize:(int)size; -(void)addSample:(double)sample; -(double)movingAverage; @end 

和执行文件:

 #import "MovingAverage.h" @implementation MovingAverage -(id)initWithSize:(int)size { if (self = [super init]) { samples = [[NSMutableArray alloc] initWithCapacity:size]; sampleCount = 0; averageSize = size; } return self; } -(void)addSample:(double)sample { int pos = fmodf(sampleCount++, (float)averageSize); [samples setObject:[NSNumber numberWithDouble:sample] atIndexedSubscript:pos]; } -(double)movingAverage { return [[samples valueForKeyPath:@"@sum.doubleValue"] doubleValue]/(sampleCount > averageSize-1?averageSize:sampleCount); } @end 

我认为你有正确的解决scheme。

如果你真的关心性能,而不是移动和移出一个dynamicresize的数组,你可以使用一个静态大小的数组,并跟踪当前的索引。

即如果N是数组的大小,%是模运算符(我不是一个客观的C程序员):

 values[current] = get_current_sample() previous = (current + N - 1) % N sum = sum + values[current] - values[previous] current = (current + 1) % N 

平均值=总和/ N。您必须分别处理预热期(在有N个样本之前)。

这可能会快得多取决于如何NSMutableArray处理内存分配。