web-dev-qa-db-fra.com

Comment calculer efficacement la moyenne à la volée (moyenne mobile)?

Je viens avec ça

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

Je pense que les points saillants de cette façon sont:
- Cela évite les gros nombres (et les débordements possibles si vous additionnez puis divisez)
- vous enregistrez un registre (pas besoin de stocker la somme)

Le problème pourrait être lié à l'erreur de sommation - mais je suppose qu'en général, il doit y avoir un nombre équilibré d'arrondis vers le haut et vers le bas afin que l'erreur ne se résume pas de façon spectaculaire.

Voyez-vous des pièges dans cette solution? Avez-vous une meilleure proposition?

38
Vit Bernatik

Votre solution est essentiellement la solution en ligne optimale "standard" pour garder une trace de la moyenne sans stocker de grosses sommes et aussi pendant l'exécution "en ligne", c'est-à-dire que vous pouvez simplement traiter un numéro à la fois sans revenir à d'autres numéros, et vous seulement utiliser une quantité constante de mémoire supplémentaire. Si vous voulez une solution légèrement optimisée en termes de précision numérique, au prix d'être "en ligne", alors en supposant que vos nombres sont tous non négatifs, triez d'abord vos nombres du plus petit au plus grand, puis traitez-les dans cet ordre, le comme vous le faites maintenant. De cette façon, si vous obtenez un tas de nombres qui sont vraiment petits à peu près égaux et que vous obtenez ensuite un grand nombre, vous pourrez calculer la moyenne avec précision sans débordement, contrairement à si vous avez d'abord traité le grand nombre.

24
user2566092