Objective-C中的移动平均
我试图找出如何从麦克风接收到的特定值中获得移动平均值。我有一个Objective-C中的移动平均,objective-c,nsarray,moving-average,Objective C,Nsarray,Moving Average,我试图找出如何从麦克风接收到的特定值中获得移动平均值。我有一个frequencychangedwhithvalue函数调用我的测量方法。这意味着我得到的频率值在一秒钟内最多变化10次。我现在感兴趣的是如何从所有这些变化的值中得出一个平均数。我该怎么做 代码 我有一个: // MovingAverage.h @interface MovingAverage : NSObject @property (readonly, nonatomic) float movingAverage; @prop
frequencychangedwhithvalue
函数调用我的测量方法。这意味着我得到的频率值在一秒钟内最多变化10次。我现在感兴趣的是如何从所有这些变化的值中得出一个平均数。我该怎么做
代码
我有一个:
// MovingAverage.h
@interface MovingAverage : NSObject
@property (readonly, nonatomic) float movingAverage;
@property (readonly, nonatomic) float cumulativeAverage;
- (id)initWithPeriod:(NSUInteger)period;
- (void)addDatum:(NSNumber *)datum;
@end
// MovingAverage.m
#import "MovingAverage.h"
@interface MovingAverage ()
@property (strong, nonatomic) NSMutableArray *queue;
@property (assign, nonatomic) NSUInteger period;
@property (assign, nonatomic) NSUInteger count;
@property (assign, nonatomic) float movingAverage;
@property (assign, nonatomic) float cumulativeAverage;
@end
@implementation MovingAverage
- (id)initWithPeriod:(NSUInteger)period {
self = [self init];
if (self) {
_period = period;
// with arc
_queue = [NSMutableArray array];
// without arc
_queue = [[NSMutableArray alloc] init];
}
return self;
}
- (void)addDatum:(NSNumber *)datum {
[self.queue insertObject:datum atIndex:0];
float removed = 0;
float datumf = [datum floatValue];
if (self.queue.count > self.period) {
removed = [[self.queue lastObject] floatValue];
[self.queue removeLastObject];
}
self.movingAverage = self.movingAverage - (removed / self.period) + (datumf / self.period);
// compute the cumulative average
self.cumulativeAverage = self.cumulativeAverage + (datumf - self.cumulativeAverage) / ++self.count;
}
// if non-ARC
- (void)dealloc {
[_queue release];
[super dealloc];
}
@end
只需保存一个数组和元素总数即可。由于它是移动平均数,因此元素计数可能高于数组元素的总计数,您需要计算此计数的剩余部分 例如:
@property (nonatomic,retain) NSMutableArray* elements;
@property (nonatomic,assign) NSUInteger lastIndex;
@property (nonatomic,assign) double average;
初始化元素并使其保持N个值(长值的NSNumber)。您应该能够通过调用以下简单方法来更改平均值:
- (void) changeAverage: (long) newValue
{
NSUInteger index= (++lastIndex) % elements.count;
NSNumber* oldValue= elements[index]; // same as [elements objectAtIndex: index];
average+= (double)newValue/elements.count - (double)[oldValue longValue]/elements.count;
// The cast is to don't lose the decimal precision while dividing these numbers.
[elements replaceObjectAtIndex: index withObject: @(newValue)];
// @(newValue) is the same as [NSNumber numberWithLong: newValue];
}
在这里可以看到一个类似的问题:因为您没有使用ARC,所以在这种情况下pool=nil是无用的。通常,如果没有相反的理由,你会使用。代码非常简单,不需要从某个地方抄袭它。@RamyAlZuhouri-但通常都是很好的做法。就我看来,它更多的是一种冗余,而不是一种好的做法。我认为您可能需要在构造函数中的某个地方初始化队列(NSMutableArray)。这一点很好。我在getter中有一个懒惰的init,我没有粘贴到这里。将添加到init。好的,但对于非Arc,您正在释放dealloc中的队列(这对我来说很好),但在创建时它实际上不会被保留。您可能需要考虑:_queue=[[NSMutableArray alloc]initWithCapacity:_period];而不是_queue=[NSMutableArray]再次右击。我忘了底部有非圆弧选项。
- (void) changeAverage: (long) newValue
{
NSUInteger index= (++lastIndex) % elements.count;
NSNumber* oldValue= elements[index]; // same as [elements objectAtIndex: index];
average+= (double)newValue/elements.count - (double)[oldValue longValue]/elements.count;
// The cast is to don't lose the decimal precision while dividing these numbers.
[elements replaceObjectAtIndex: index withObject: @(newValue)];
// @(newValue) is the same as [NSNumber numberWithLong: newValue];
}