Berechne Rolling / Moving Average in C ++
Ich weiß, das ist erreichbar mit boost als pro:
Aber ich möchte wirklich vermeiden, mit zu steigern. Ich habe gegoogelt und nicht gefunden, einen geeigneten lesbar oder Beispiele.
Grundsätzlich möchte ich Spur den gleitenden Durchschnitt der ein kontinuierlicher Strom von einem Strom von floating-point-zahlen über die letzten 1000 zahlen-Daten-Beispiel.
Was ist der einfachste Weg, dies zu erreichen?
Experimentierte ich mit mit einem kreisförmigen array, exponential moving average und ein einfacher gleitender Durchschnitt und festgestellt, dass die Ergebnisse aus der kreisförmigen array geeignet, meine Bedürfnisse am besten.
Kommentar zu dem Problem
Warum wollen Sie vermeiden Sie die Verwendung von Boost? Es ist eine gut etablierte, komplett-gebraucht und gut unterstützte Satz von C++ - Bibliotheken. Es gibt keinen Grund, das Rad neu zu erfinden.
Welchen Teil dieser sind Sie stecken? Wissen Sie, welche moving average Algorithmus, den Sie möchten, aus mathematischer Sicht?
Durchschnitt funktioniert für ganze zahlen, aber für floating-point können Sie erleben seltsame Verhalten aufgrund von Rundungen und Unterschiede der Größenordnung...
Der trick ist die Vermeidung einer Puffer-zu-AveragingBuffer kopieren. Einige Leute hier wollen, dass Sie eine separate Puffer für die vorhergehenden Proben. Dies kann nicht notwendig sein, die Proben kommen aus einem Puffer.
InformationsquelleAutor der Frage goji | 2012-06-12
Du musst angemeldet sein, um einen Kommentar abzugeben.
Müssen Sie einfach nur ein kreisförmiges array mit 1000 Elementen, wo Sie hinzufügen, um das element zu dem vorherigen element, und speichern Sie es... Es wird zu einer Erhöhung der Summe, wo man immer die Summe zwischen zwei Paaren von Elementen, und dividieren durch die Anzahl der Elemente zwischen Ihnen, der Ertrag der Durchschnitt.
InformationsquelleAutor der Antwort Karthik Kumar Viswanathan
Wenn sich Ihre Bedürfnisse sind einfach, Sie könnten nur versuchen, mit einem exponentiellen gleitenden Durchschnitt.
http://en.wikipedia.org/wiki/Moving_average#Exponential_moving_average
Einfach gesagt, Sie machen eine Akkumulator-variable, und wie dein code aussieht, bei jeder Probe, die code-updates der Akku mit dem neuen Wert. Wählen Sie eine Konstante "alpha", der zwischen 0 und 1, und berechnen Sie diese:
Brauchen Sie nur zu finden, die einen Wert von "alpha", bei denen die Wirkung einer bestimmten Probe dauert nur etwa 1000 Proben.
Hmm, ich bin eigentlich nicht sicher, dass dies für Sie geeignet ist, nun habe ich ihn hier. Das problem ist, dass 1000 ist eine ziemlich lange Fenster für einen exponentiellen gleitenden Durchschnitt; ich bin nicht sicher, es ist eine alpha, die verbreitet sich der Durchschnitt über die letzten 1000 zahlen, ohne Unterlauf in der floating-point-Berechnung. Aber wenn Sie wollten eine kleinere Durchschnittliche, wie 30 zahlen oder so, ist dies eine sehr einfache und schnelle Art und Weise, es zu tun.
InformationsquelleAutor der Antwort steveha
Können Sie annähernd einen Durchschnitt durch die Anwendung eines gewichteten durchschnittlichen auf Ihren input-stream.
Diese Weise brauchen Sie nicht zu pflegen 1000 Eimer. Jedoch, es ist eine Annäherung, so ist es Wert nicht genau mit einem true-Durchschnitt.
Edit: Gerade bemerkt, @steveha post. Dies entspricht dem exponentiellen gleitenden Durchschnitt mit der alpha 1/N (ich war mit dem N 1000, in diesem Fall zu simulieren, 1000-Eimer).
InformationsquelleAutor der Antwort jxh
Beachten Sie, dass die folgenden updates der total_ als Elemente Hinzugefügt/ersetzt, Vermeidung von Kosten O(N) traversal, die zur Berechnung benötigte für die durchschnittlichen - auf Nachfrage.
Total
ist aus einem anderen parameter ausT
zu unterstützen, z.B. mit einemlong long
wenn insgesamt 1000long
s, einint
fürchar
s, oder eindouble
zu insgesamtfloat
s.Dies ist ein wenig fehlerhaft, dass
num_samples_
gehen könnte VergangenheitINT_MAX
- wenn Sie kümmern Sie könnten eineunsigned long long
, oder verwenden Sie eine zusätzliche bool-Daten Mitglied aufnehmen, wenn der container zum ersten mal gefüllt, während Radfahren num_samples_ rund um das array (am besten dann in etwas harmlosen wie "pos
").InformationsquelleAutor der Antwort Tony Delroy
Einfach Klasse zum berechnen von Durchschnitt und auch rollende Standardabweichung:
InformationsquelleAutor der Antwort Erik Aronesty
Könnten Sie implementieren eine Ringpuffer. Machen Sie ein array mit 1000 Elementen, und einige Felder zum speichern der start-und end-Indizes und Gesamtgröße. Dann speichern nur die letzten 1000 Elemente im Ringpuffer, und berechnen den durchschnittlichen Bedarf.
InformationsquelleAutor der Antwort Tim
einen einfachen gleitenden Durchschnitt für 10 Artikel, mit einer Liste:
InformationsquelleAutor der Antwort Pedro Soares
Ein Weg sein kann, um Zirkular speichern der Werte in dem Puffer-array. und berechnen Sie die Durchschnittliche auf diese Weise.
Das ganze läuft in einer Schleife, wo die meisten aktuellen Wert dynamisch ist.
InformationsquelleAutor der Antwort Nilesh Kumar Jha
Benutze ich diese sehr oft in harte Echtzeit-Systeme, die ziemlich verrückt update-raten (50kilosamples/sec) Als Ergebnis habe ich in der Regel precompute die Skalare.
Zur Berechnung eines gleitenden Durchschnitts von N Proben:
scalar1 = 1/N;
scalar2 = 1 - scalar1; //oder (1 - 1/N)
dann:
Durchschnitt = currentSample*scalar1 + Durchschnitt*scalar2;
Beispiel: gleitender Durchschnitt der 10 Elemente
Hinweis: dies ist nur eine praktische Umsetzung der Antwort durch steveha oben.
Manchmal ist es einfacher zu verstehen, ein konkretes Beispiel.
InformationsquelleAutor der Antwort baumann