着信数値の平均値を報告する必要があります。何らかのデータ構造を使用してすべての値を追跡し、それらを合計して値の数で割って平均を計算することなく、どのようにそれを行うことができますか?
5 に答える
あなたが数字を持っていて、a[1] a[2] ... a[n]
それらの平均がavg(n) = (a[1] + ... + a[n]) / n
であることがわかっているなら、あなたが別の数字を得るとき、あなたはa[n + 1]
することができます:
avg(n + 1) = (avg(n) * n + a[n + 1]) / (n + 1)
一部の浮動小数点エラーは避けられませんが、これをテストして、十分かどうかを確認する必要があります。
オーバーフローを回避するには、最初に除算を実行できます。
avg(n + 1) = (avg(n) / (n + 1)) * n + (a[n + 1] / (n + 1))
私が完全に間違っていなければ、次のavg(n+1)
方法でも計算できます。
avg(n+1) = (a[1]+ ... + a[n+1]) / (n+1) =
= (a[1]+ ... + a[n])/(n+1) + a[n+1]/(n+1) =
= (n(a[1]+ ... + a[n])/n) / (n+1) + a[n+1]/(n+1) =
= n*avg(n) / (n+1) + a[n+1]/(n+1) =
= n/(n+1) * avg(n) + a[n+1]/(n+1)
したがって、古い平均を で乗算しn/(n+1)
、新しい要素を で割った値を追加しn+1
ます。どれだけ高くなり、値がどれだけ大きいかに応じてn
、これにより丸め誤差が減少する可能性があります...
編集:もちろんn/(n+1)
、フロートを使用して計算する必要があります。そうしないと、常に 0 がレンダリングされます...
現在の合計とカウントを維持します。着信番号ごとに両方を更新します。
avg = sum / count.
平均を計算するために必要なのは、合計と受け取った数字の数だけです。
合計を追跡する必要はなく、カウンターのみを追跡する必要があります。
class Averager {
float currentAverage;
size_t count;
float addData (float value) {
this->currentAverage += (value - this->currentAverage) / ++count;
return this->currentAverage;
}
}