¿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?
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.
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.
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