要するにa+b
、切り捨てによる精度の低下がゼロに向かうのではなく、ゼロから離れるように実行するにはどうすればよいでしょうか?
長い物語
セットのサンプル平均と分散を計算する目的で、長い一連の浮動小数点値の合計を計算しています。Var(X) = E(X 2 ) - E(X) 2であるため、すべての数値の実行中のカウント、これまでのすべての数値の合計、およびこれまでのすべての数値の 2 乗の合計を維持するだけで十分です。
ここまでは順調ですね。
ただし、 E(X 2 ) > E(X) 2であることが絶対に必要であり、浮動小数点の精度が原因で常にそうとは限りません。疑似コードでは、問題は次のとおりです。
int count;
double sum, sumOfSquares;
...
double value = <current-value>;
double sqrVal = value*value;
count++;
sum += value; //slightly rounded down since value is truncated to fit into sum
sumOfSquares += sqrVal; //rounded down MORE since the order-of-magnitude
//difference between sqrVal and sumOfSquares is twice that between value and sum;
変数シーケンスの場合、これは大きな問題ではありません。分散をわずかに過小評価することになりますが、多くの場合、大きな問題にはなりません。ただし、ゼロ以外の平均値を持つ定数またはほぼ定数のセットの場合、 E(X 2 ) < E(X) 2を意味する可能性があり、その結果、計算された分散が負になり、コードを消費するという期待に反します。
今、私は魅力的なソリューションではないカハン総和について知っています。第一に、コードが最適化の気まぐれの影響を受けやすくなります (最適化フラグに応じて、コードはこの問題を示す場合と示さない場合があります)。第二に、問題は実際には精度によるものではありません。これで十分です。ゼロに向かってエラー。行を実行できれば
sumOfSquares += sqrVal;
sqrVal が sumOfSquares の精度に丸められるのではなく、切り上げられるようにするには、数値的に妥当な解決策が必要です。しかし、どうすればそれを達成できますか?
編集:完成した質問 - タグフィールドのドロップダウンリストでEnterキーを押すと、とにかく質問が送信されるのはなぜですか?