Ich versuche einen Weg zu finden, um einen gleitenden kumulativen Durchschnitt zu berechnen, ohne die Anzahl und die Gesamtdaten zu speichern, die bisher empfangen wurden.
Ich habe zwei Algorithmen entwickelt, aber beide müssen die Anzahl speichern:
- neuer Durchschnitt = ((alte Zählung * alte Daten) + nächste Daten) / nächste Zählung
- neuer Durchschnitt = alter Durchschnitt + (nächste Daten - alter Durchschnitt) / nächste Zählung
Das Problem bei diesen Methoden ist, dass die Anzahl immer größer wird, was zu einem Genauigkeitsverlust im resultierenden Durchschnitt führt.
Die erste Methode verwendet die alte und die nächste Zählung, die offensichtlich 1 voneinander entfernt sind. Dies brachte mich zu dem Gedanken, dass es vielleicht eine Möglichkeit gibt, die Zählung zu entfernen, aber leider habe ich sie noch nicht gefunden. Es hat mich zwar ein bisschen weiter gebracht, was zur zweiten Methode führte, aber die Anzahl ist immer noch vorhanden.
Ist es möglich oder suche ich nur das Unmögliche?
quelle
Antworten:
Sie können einfach tun:
Wo
N
ist die Anzahl der Stichproben, über die Sie einen Durchschnitt bilden möchten? Beachten Sie, dass diese Annäherung einem exponentiellen gleitenden Durchschnitt entspricht. Siehe: Berechnen Sie den gleitenden / gleitenden Durchschnitt in C ++quelle
5
Proben eingeben , beträgt der Durchschnitt 0,67.avg
initialisiert auf erhalten0
Sie3.36
nach 55
s und4.46
nach 10: cpp.sh/2ryql. Für lange Durchschnittswerte ist dies sicherlich eine nützliche Annäherung.Dies setzt voraus, dass sich die Anzahl nur um einen Wert ändert. Falls es um M Werte geändert wird, dann:
Dies ist die mathematische Formel (ich glaube die effizienteste). Glauben Sie, dass Sie selbst weiteren Code erstellen können
quelle
m
neue Werte in den neuen Durchschnitt einbezogen . Ich glaube, dasssum of new value
hier die Summe derm
neuen Werte gemeint ist , die zur Berechnung des neuen Durchschnitts verwendet werden.new_average = (old_average * (n-1) + new_value) / n
- Entfernt eine der Teilungen.Aus einem Blog über das Ausführen von Stichprobenvarianzberechnungen, in dem der Mittelwert auch nach der Welford-Methode berechnet wird :
Schade, dass wir keine SVG-Bilder hochladen können.
quelle
Hier ist noch eine weitere Antwort Angebot Kommentierung wie Muis , Abdullah Al-Ageel und Flip ‚s Antwort sind alle mathematisch die gleiche Sache außer dass sie unterschiedlich geschrieben sind.
Sicher, wir haben José Manuel Ramos 'Analyse, die erklärt, wie sich Rundungsfehler geringfügig voneinander auswirken, aber das hängt von der Implementierung ab und würde sich ändern, je nachdem, wie jede Antwort auf Code angewendet wurde.
Es gibt jedoch einen ziemlich großen Unterschied
Es ist in Muis 's
N
, Flip ' sk
, und Abdullah Al-Ageel ‚sn
. Abdullah Al-Ageel nicht ganz erklären , wasn
sein sollte, aberN
undk
unterscheiden sich dadurch , dassN
ist „ die Anzahl der Proben , bei denen Sie Durchschnitt wollen über “ , währendk
die Anzahl der abgetasteten Werte. (Obwohl ich Zweifel habe, ob das AufrufenN
der Anzahl der Proben korrekt ist.)Und hier kommen wir zur Antwort unten. Es ist im Wesentlichen der gleiche alte exponentiell gewichtete gleitende Durchschnitt wie die anderen. Wenn Sie also nach einer Alternative suchen, hören Sie hier auf.
Exponentiell gewichteter gleitender Durchschnitt
Anfänglich:
Für jeden Wert:
Der Unterschied ist der
min(counter, FACTOR)
Teil. Dies ist das gleiche wie zu sagenmin(Flip's k, Muis's N)
.FACTOR
ist eine Konstante, die beeinflusst, wie schnell der Durchschnitt den neuesten Trend "einholt". Je kleiner die Zahl, desto schneller. (1
Es ist kein Durchschnitt mehr und wird nur zum neuesten Wert.)Diese Antwort erfordert den laufenden Zähler
counter
. Wenn es problematisch ist,min(counter, FACTOR)
kann das durch just ersetzt werdenFACTOR
, was es zu Muis 'Antwort macht. Das Problem dabei ist, dass der gleitende Durchschnitt von allem beeinflusst wird, wasaverage
initiiert wurde. Wenn es auf initialisiert0
wurde, kann es lange dauern, bis sich diese Null aus dem Durchschnitt herausarbeitet.Wie es am Ende aussieht
quelle
max(counter, FACTOR)
.min(counter, FACTOR)
wird immer FACTOR zurückgeben, oder?min(counter, FACTOR)
geht darum, die Aufwärmphase zu berücksichtigen. Wenn Ihr FAKTOR (oder N oder die gewünschte Probenanzahl) 1000 beträgt, benötigen Sie mindestens 1000 Proben, bevor Sie ein genaues Ergebnis erhalten, da bei allen vorherigen Aktualisierungen davon ausgegangen wird, dass Sie 1000 Proben haben, wenn Sie nur dürfen habe 20.Die Antwort von Flip ist rechnerisch konsistenter als die von Muis.
Bei Verwendung des Doppelnummernformats konnten Sie das Rundungsproblem im Muis-Ansatz erkennen:
Wenn Sie dividieren und subtrahieren, wird im vorherigen gespeicherten Wert eine Rundung angezeigt, die sich ändert.
Der Flip-Ansatz behält jedoch den gespeicherten Wert bei und verringert die Anzahl der Teilungen, wodurch die Rundung verringert und der auf den gespeicherten Wert übertragene Fehler minimiert wird. Wenn Sie nur hinzufügen, werden Rundungen angezeigt, wenn etwas hinzugefügt werden muss (wenn N groß ist, gibt es nichts hinzuzufügen).
Diese Änderungen sind bemerkenswert, wenn Sie einen Mittelwert aus großen Werten erstellen, deren Mittelwert gegen Null tendiert.
Ich zeige Ihnen die Ergebnisse mit einem Tabellenkalkulationsprogramm:
Erstens wurden die Ergebnisse erhalten:
Die Spalten A und B sind die Werte n und X_n.
Die C-Spalte ist der Flip-Ansatz und die D-Spalte ist der Muis-Ansatz, das Ergebnis wird im Mittelwert gespeichert. Die Spalte E entspricht dem bei der Berechnung verwendeten Mittelwert.
Ein Diagramm, das den Mittelwert der geraden Werte zeigt, ist das nächste:
Wie Sie sehen können, gibt es große Unterschiede zwischen beiden Ansätzen.
quelle
Ein Beispiel mit Javascript zum Vergleich:
https://jsfiddle.net/drzaus/Lxsa4rpz/
Code-Snippet anzeigen
quelle
In Java8:
Sie haben auch
IntSummaryStatistics
,DoubleSummaryStatistics
...quelle
Eine nette Python-Lösung basierend auf den obigen Antworten:
Verwendung:
quelle