2017-05-20 14 views
2

長いdouble型の配列、たとえばN == 1000000があるとします。合計の誤差が最小になるように、2倍の平均を計算するにはどうすればよいですか?

平均を計算するための2つの単純なアプローチがあります。最初

double result = 0; 
for (double x : arr) { 
    result += x; 
} 
result /= arr.size(); 

これは値の合計が非常に大きい場合、不正確な場合があります。浮動小数点数は精度を失います。

別のアプローチは、次のとおりです。

double result = 0; 
for (double x : arr) { 
    result += x/arr.size(); 
} 

数字が小さいときには、精度を失う可能性があります。

浮動小数点数の単純な平均を計算するためのフェイルセーフな方法はありますか?標準ライブラリのみを使用するソリューションは高く評価されています。

+3

クレームは無意味ですが、値の大きさに基づいて精度を失うことはありません。これが浮動小数点の「浮動小数点数」が処理するものです。 * double *が格納できる有効数字の桁数は値に依存しませんが、これ以上表示すると間違った値になります。 –

+2

@HansPassantバイナリ表現には制限があります。 2つの浮動小数点数を加算すると、指数が一致します。つまり、4桁の10進数しか表現できない場合、1.234e0を1.234e3に追加すると、最初に0.001e3に変換され、下位桁が破棄されます。 –

答えて

3

ダブルスの精度をさらに絞りたい場合は、 Kahan summationを使用し、最終的に要素数で除算することができます。しかし私が知っているカハン和の標準的なライブラリ実装はありません。

基本的には最初の実装を使用し、結果を倍精度に変換するだけで、簡単な標準的な方法(ほとんど不正行為のような)は長い倍精度を使用した計算になります。

1

精度の低下を減らす1つの方法は、倍精度をソートし、最小値から順にソート順に加算し、最後に最終和を2倍数で除算することです。

だから、あなたが必要なツールはstd::sortstd::accumulateと、昔ながらの分裂/だろう。

1

いわゆるナイーブな方法はナイーブではありません。データは何を意味し、それらの値をどれくらい正確に測定できますか?答えが非常に珍しいものでない限り、二倍の単純な方法は問題ありません。しかし、浮動小数点は、一般的な使用のために少し不十分である。

小さな絶対値を最初に追加すると、余分なビット精度が得られることがあります。それは並べ替えが必要です。データがすべて特定のしきい値を超えている場合は、最小値を減算するともう1つのビットが得られます。

部分合計と部分平均を保存し、処理された部分平均*数が部分合計の一定の許容値内にあるかどうかを各段階で確認することもできます。それはあなたに余分な正確さを与えることはありませんが、あなたの目的のためにfpuがあまりにも不正確であるかどうかを教えてくれます。

また、長い倍精度を使用することも、独自の拡張精度浮動小数点ライブラリをコーディングすることもできます(または、他の人を使用することもできます)。しかし、その解決策はますます勇敢になっています。

関連する問題