8

私はC#/。NETで科学計算と視覚化プロジェクトに取り組んでおり、doubleすべての物理量を表すためにsを使用しています。浮動小数点数には常に少しの丸めが含まれるため、次のような等価比較を行う簡単な方法があります。

static double EPSILON = 1e-6;

bool ApproxEquals(double d1, double d2) {
    return Math.Abs(d1 - d2) < EPSILON;
}

かなり標準的です。

EPSILONただし、 「等しい」量の誤差が予想よりも大きい状況に遭遇すると、常に大きさを調整する必要があります。たとえば、5つの大きなdoublesを掛け合わせてから、5回割ると、精度が大幅に低下します。EPSILONを大きくしすぎることはできません。そうしないと、誤検知が発生しますが、それでも誤検知が発生します。

一般に、私たちのアプローチは、より数値的に安定したアルゴリズムを探すことでしたが、プログラムは非常に計算的であり、私たちができることはそれほど多くありません。

誰かがこの問題に対処するための良い戦略を持っていますか?タイプを少し調べましたが、Decimalパフォーマンスが心配で、問題が解決するのか、それともわかりにくいだけなのかを知るのに十分な知識がありません。これらの問題を解決できるかどうかを確認することで、中程度のパフォーマンスヒット(たとえば2倍)を受け入れるつもりDecimalですが、パフォーマンスは間違いなく懸念事項であり、コードはほとんど浮動小数点演算によって制限されているため、そうではないと思います不当な懸念。私は人々が100倍の違いを引用しているのを見てきましたが、それは間違いなく受け入れられないでしょう。

また、に切り替えるとDecimal、ライブラリでの一般的なサポートの欠如など、他の問題が発生するMathため、たとえば、独自の平方根関数を作成する必要があります。

何かアドバイス?

編集:ところで、私が(相対的な比較の代わりに)一定のイプシロンを使用しているという事実は私の質問のポイントではありません。例としてそこに置いておきますが、実際には私のコードの一部ではありません。数値が非常に大きくなり、その後再び小さくなると精度が低下することから問題が発生するため、相対比較に変更しても、質問に違いはありません。たとえば、値が1000の場合、一連の計算を実行すると、まったく同じ数値になるはずですが、精度が低下したため、実際には1001になります。次に、これらの数値を比較すると、相対比較を使用するか絶対比較を使用するかは重要ではありません(問題と規模に意味のある方法で比較を定義している限り)。

とにかく、Mitch Wheatが示唆したように、アルゴリズムの並べ替えは問題の解決に役立ちました。

4

3 に答える 3

5

これは.NETに固有の問題ではありません。精度の低下を減らすための戦略は、計算を並べ替えて、大量に少量を掛け、同様のサイズの数量を加算/減算することです(計算の性質を変更することはありません)。

あなたの例では、5つの大きな量を掛け合わせてから、5つの大きな量で割るのではなく、並べ替えて各大きな量を除数の1つで割ってから、これらの5つの部分的な結果を掛けます。

興味を持っている?(まだ読んでいない場合):すべてのコンピューター科学者が浮動小数点演算について知っておくべきこと

于 2010-02-12T00:32:16.530 に答える
2

もちろん、あなたの最善の答えは常により良いアルゴリズムです。しかし、値がすべて1桁以内に収まらない場合は、固定イプシロンを使用するのは適切な戦略ではないように思われます。代わりに実行したいのは、値がある程度の妥当な精度内で等しいことを保証することです。

// are values equal to within 12 (or so) digits of precision?
//
bool ApproxEquals(double d1, double d2) {
    return Math.Abs(d1 - d2) < (Math.Abs(d1) * 1e-12);
}

これがC++の場合、仮数と指数を別々に比較するためにいくつかのトリックを引き出すこともできますが、管理されていないコードでこれを安全に行う方法は考えられません。

于 2010-02-12T01:31:13.577 に答える
1

実数の通常の表現方法により、これはCで(そしておそらく安全でないC#で)行うことができます。

if (llabs(*(long long)&x - *(long long)&y) <= EPSILON) {
    // Close enough
}

これは明らかに移植性がなく、おそらく悪い考えですが、スケールに依存しないという大きな利点があります。つまり、EPSILONは1、10、100などの小さな定数(必要な許容値に応じて)にすることができ、指数に関係なく比例丸め誤差を正しく処理します。

免責事項:これは私自身の私的な発明であり、手がかりを持っている人(たとえば、離散算術のバックグラウンドを持つ数学者など)によって精査されたことはありません。

于 2010-02-12T00:56:37.320 に答える