web-dev-qa-db-ja.com

オンザフライで効率的に平均を計算する方法(移動平均)

これを思いつきます

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

この方法のハイライトは次のとおりです。
-大きな数を回避します(合計してから除算する場合にオーバーフローが発生する可能性があります)
-1つのレジスターを保存します(合計を保存する必要はありません)

問題は加算エラーにある可能性がありますが、一般に、切り上げと切り捨てのバランスの取れた数があるため、エラーが劇的に合計されないものと想定しています。

このソリューションには落とし穴がありますか?より良い提案はありますか?

38
Vit Bernatik

あなたのソリューションは、本質的には、大きな金額を保存することなく、また「オンライン」で実行している間、平均のランニングトラックを維持するための「標準」最適オンラインソリューションです。一定量の追加メモリを使用します。 「オンライン」という犠牲を払って、数値の精度に関してわずかに最適化されたソリューションが必要な場合は、数値がすべて負でないと仮定し、最初に数値を最小から最大に並べ替えてから、その順序で処理します。今と同じように。そうすれば、ほぼ等しい数の小さな数字を取得してから1つの大きな数字を取得した場合、大きな数字を最初に処理した場合とは対照的に、アンダーフローなしで正確に平均を計算できます。

24
user2566092