2015-03-02 4 views
22

ich komme mit diesemWie kann der Durchschnitt im laufenden Betrieb effizient berechnet werden (gleitender Durchschnitt)?

n=1; 
curAvg = 0; 
loop{ 
    curAvg = curAvg + (newNum - curAvg)/n; 
    n++; 
} 

Ich denke, Highlights dieser Art sind:
- Es große Zahlen vermeidet
(und möglichen Überlauf, wenn Sie und teilen sich dann summieren würde) - Sie ein Register speichern (nicht müssen die Summe speichern)

Das Problem könnte mit Summierungsfehler sein - aber ich gehe davon aus, dass es im Allgemeinen ausgeglichene Zahlen von Aufrunden und Abrunden geben sollte, so dass der Fehler nicht dramatisch zusammenfasst.

Siehst du irgendwelche Fallstricke in dieser Lösung? Haben Sie einen besseren Vorschlag?

+0

Ich verstehe Ihre Formel nicht. Für '1 2' und' 3' als nächstes würden Sie 'curAvg = 1.5 + (3 - 1.5)/2 = 1.5 + 0.75 = 2.25' machen, was wäre falsch? – IVlad

+1

Ähnliche Fragen: http://stackoverflow.com/questions/12636613/how-to-calculate-moving-average-witout-keeping-the-count-and-data-total –

+0

@IVlad: Schleife 1: curAvg = 0 + (1-0)/1 = 1; n = 2
Schleife 2: curAvg = 1 + (2-1) /2 = 1,5; n = 3
Schleife 3: curAvg = 1,5 + (3-1,5)/3 = 2; n = 4 –

Antwort

14

Ihre Lösung ist im Wesentlichen die "standardmäßige" Online-Lösung für eine durchschnittliche Laufstrecke, ohne große Summen zu speichern und auch "online" zu fahren, dh Sie können nur eine Nummer auf einmal bearbeiten, ohne zu anderen Nummern zurückzukehren , und Sie verwenden nur eine konstante Menge an zusätzlichem Speicher. Wenn Sie eine etwas optimierte Lösung in Bezug auf die numerische Genauigkeit wollen, auf Kosten von "online", dann unter der Annahme, Ihre Zahlen sind alle nicht negativ, dann sortieren Sie Ihre Zahlen zuerst vom kleinsten zum größten und dann verarbeiten sie in dieser Reihenfolge, die So wie Sie es jetzt tun. Auf diese Weise, wenn Sie eine Reihe von Zahlen, die wirklich klein sind etwa gleich und dann erhalten Sie eine große Zahl, können Sie den Durchschnitt genau ohne Unterlauf zu berechnen, im Gegensatz zu, wenn Sie die große Zahl zuerst verarbeitet.

-4

Die obige Formel ist Unsinn. Einfache Mathematik und Präzision diktieren würde:

n ist der Wiederholungszähler, AV läuft Durchschnitt ist newVal neuen Wert

Initialisierung n=0, AV=0

((AV * n) + newVal)/(n+1) = AV 

Es gibt keine Abkürzung, müssen Sie haben alle Zahlen und teilen sie durch die Anzahl der Iterationen, aber Sie können eine der Zahlen neu erstellen, indem Sie wissen, welche Iteration es ist, es ist ein Tossup, eine laufende Summe zu behalten oder sie neu zu berechnen. Die Zeit für die Neuberechnung ist mit hohen Kosten verbunden, die Kosten für die Speicherung einer Zahl sind wahrscheinlich mit geringen Speicherkosten verbunden, und der neu zu berechnende Code wäre sicherlich mehr als der Speicherplatz für die Summe und die Iteration.

+1

Sie sind genau die gleiche Formel unterschiedlich präsentiert. Addiere und subtrahiere AV zum Nominator deiner Form und du erhältst (AV * (n + 1) + neuesVal - AV)/(n + 1), das zu - AV * (n + 1)/(n +) umgeordnet werden kann 1) + (neuVal - AV)/(n + 1) – Itai

+2

Ihre Lösung ist mathematisch korrekt, aber Sie haben eine zusätzliche Multiplikation. Versuchen Sie, einige Zahlen zu setzen, und Sie werden sehen, dass meine Lösung ganz gut funktioniert ... Vielleicht können Sie auch versuchen, etwas gesunden Menschenverstand zu verwenden und ein bisschen bescheidener zu sein. Wenn 6 Personen zustimmen, dass es eine "optimale Standardlösung" ist, dann ist es möglicherweise nicht korrekt zu schreiben, dass es "ein Unsinn" ist. –