2011-12-09 2 views
2

I 0의 범위의 신호 강도 값이 매 초마다 업데이트되는 정수 속성을 가지고 지난 10, 25, 50 측정 동안 이동 평균.계산하는 이동 - 평균은

가장 효율적인 방법은 무엇입니까?

현재 NSMutableArray를 사용하여 FIFO 대기열 집합을 구현하고 배열에 필요한 수의 항목이있는 경우 끝에 새 값을 추가 할 때마다 선행 값을 팝핑 할 생각입니다. 그러나이 작업을 수행하는보다 효율적인 방법이 있는지 확실하지 않습니다.

답변

4

대기열이 올바른 방법입니다. 실제 효율은 평균을 다시 계산하는 방법과 함께 제공됩니다.

는 그것은으로 수행해야합니다

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

즉 새로운 실행 평균이 단순히 이전 평균 뺀 떨어 가장 오래된 가치의 무게, 플러스 당신이 큐에 최신 값의 무게입니다.

+0

'[queue dequeue] 란 무엇을 의미합니까? – progrmr

+0

@progrmr : 내 Objective-C 구문이 녹슬니다. 나는 'dequeue'라는 메시지를 'queue'객체에 보냈습니다. 즉, 어떻게 든 큐를 구현한다고 가정하고 있거나 기존 큐 클래스 중 하나를 사용합니다 (있는 경우). – ArjunShankar

1

나는 당신에게 맞는 솔루션이 있다고 생각합니다.

동적으로 크기가 조정 된 배열에서 물건을 이동하는 대신 정적 크기의 배열을 사용하고 현재 색인을 추적 할 수 있습니다.

e.e. 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가 메모리 할당을 처리하는 방법에 따라 훨씬 빨라질 수 있습니다.

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 

과 꼬마 도깨비 파일 :

#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

안녕하세요! 방금 당신의 솔루션을 시도했습니다. 이것은 샘플 크기가 5 일 때만 잘 작동합니다. 그보다 큰 값 (예 : 10, 20 정도)을 설정하면 값이 감소합니다. 예 : 매번 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

그건 완벽하게 이해가됩니다! 감사. –

관련 문제