¿Cómo calcular eficientemente el promedio sobre la marcha (promedio móvil)?


Se me ocurre esto

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

Creo que lo más destacado de esta manera son:
- Evita números grandes (y posible desbordamiento si suma y luego divide)
- se guarda un registro (no es necesario almacenar suma)

El problema podría estar con el error de suma, pero supongo que generalmente habrá números equilibrados de redondeo hacia arriba y hacia abajo para que el error no se sume dramáticamente.

¿Ves algún escollo en esta solución? ¿Tienes alguna propuesta mejor?

Author: Vit Bernatik, 2015-03-03

2 answers

Su solución es esencialmente la solución en línea óptima "estándar" para mantener una pista de ejecución de promedio sin almacenar grandes sumas y también mientras se ejecuta "en línea", es decir, solo puede procesar un número a la vez sin volver a otros números, y solo utiliza una cantidad constante de memoria adicional. Si desea una solución ligeramente optimizada en términos de precisión numérica, a costa de estar "en línea", asumiendo que sus números no son negativos, ordene sus números primero de más pequeño a más grande y luego procesarlos en ese orden, de la misma manera que lo haces ahora. De esa manera, si obtienes un montón de números que son realmente pequeños aproximadamente iguales y luego obtienes un número grande, podrás calcular el promedio con precisión sin flujo insuficiente, en lugar de si procesaste el número grande primero.

 19
Author: user2566092,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-03-03 00:53:06

La fórmula anterior no tiene sentido. Las matemáticas simples y la precisión dictarían:

n es el contador de iteración, {[2] } se está ejecutando promedio, newVal es nuevo valor

Inicialización n=0, AV=0

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

No hay atajo, tienes que tener todos los números y dividirlos por el número de iteraciones, sin embargo, puedes reconstruir uno de los números sabiendo qué iteración es, es un tossup de mantener un total en ejecución o volver a calcularlo. El tiempo para volver a calcular está en un alto costo el costo de almacenar un número probablemente un bajo costo en términos de memoria y el código para volver a calcular sin duda sería más que la ubicación de la memoria para mantener el total y la iteración.

 -6
Author: user6760966,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-08-26 11:10:51