2011-12-09 8 views
2

の移動平均値を算出I 0の範囲の信号強度値を有する毎秒更新される整数性がある - 私は進行中の尺度を維持できるようにしたい100可変パラメータ

を最後の10,25,50回の測定で移動平均。

これを行う最も効率的な方法は何ですか?

私は現在、NSMutableArrayを使用してFIFOキューのセットを実装し、配列に必要な数のエントリがあると、最後に新しい値を追加するたびに先頭の値をポップすることを考えています。しかし、これを行うより効率的な方法があるかどうかはわかりません。

答えて

4

キューが正しい方法です。実際の効率は平均をどのように再計算するかによって決まります。それはで行われるべき

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

すなわち、新たな移動平均は、単に古い平均マイナスあなたがドロップされた最も古い値の重みに加え、あなたがキューに入れられた最新の値の重みです。

+0

'[queue dequeue]は何を意味していますか? – progrmr

+0

@progrmr:私のObjective-C構文は錆びています。私は行くつもりでしたが、メッセージ 'デキュー'をオブジェクト 'キュー'に送ります。すなわち、私は何とかキューを実装していると仮定しているか、または既存のキュークラス(存在する場合)のいずれかを使用しています。 – ArjunShankar

1

あなたは正しい解決策を持っていると思います。

あなたは本当に代わりに静的なサイズの配列を使用して、現在のインデックスを追跡することができ、動的にサイズ変更列の中と外に物事を移動するので、パフォーマンスを気にしている場合。

I.e. Nのサイズであれば、配列および%はモジュロ演算子(私は客観的Cプログラマではないよ)である:平均=合計/ N.

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

あなたはあなたの前に(個別にウォームアップ期間の治療のために持っていますN個のサンプルを有する)。

これはNSMutableArrayのは、メモリの割り当てを処理する方法に応じて、はるかに高速である可能性があります。

6

これを処理するために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 

およびimpファイル名:

#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 
+0

こんにちは!私はあなたの解決策を試しました。これは、値の減少に結果(10、20程度のような)よりもおろし金サンプルサイズは5設定値に等しい場合にのみうまく機能します。例:毎回const == 10を追加します。移動平均は、サンプルサイズが5に等しいときにのみ10を返します.10では5,20 - 2.5です。あれは正しいですか? –

+1

私はちょうど答えを編集しました: int pos = fmodf(sampleCount ++、5.0); 〜 int pos = fmodf(sampleCount ++、(float)averageSize); 基本的には、fmodfは移動平均のサンプル数でmodにする必要があります。セネーゼを作る? – earnshavian

+0

それは完璧な意味合いがあります!ありがとう。 –

関連する問題