red*_*sky 2 average objective-c moving-average ios
我有一个整数属性,每秒更新一次,信号强度值范围为0 - 100.
我希望能够在过去的10次,25次,50次测量中持续测量移动平均值.
这样做最有效的方法是什么?
我目前正在考虑使用NSMutableArray实现一组FIFO队列,并在每次在阵列具有必需条目数时在末尾添加新值时弹出前导值.但是,我不确定是否有更有效的方法来做到这一点.
我写了一个名为MovingAverage的简单类来处理这个问题.您使用要维护的周期数启动方法,并使用样本计数的模数跟踪其余部分,以了解要将其放入哪个静态槽.
初始化为
MovingAverage *avg5periods = [[MovingAverage alloc] initWithSize:5];
Run Code Online (Sandbox Code Playgroud)
添加项目:
[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
Run Code Online (Sandbox Code Playgroud)
头文件:
#import <Foundation/Foundation.h>
@interface MovingAverage : NSObject {
NSMutableArray *samples;
int sampleCount;
int averageSize;
}
-(id)initWithSize:(int)size;
-(void)addSample:(double)sample;
-(double)movingAverage;
@end
Run Code Online (Sandbox Code Playgroud)
和实施文件:
#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
Run Code Online (Sandbox Code Playgroud)