私は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が示唆したように、アルゴリズムの並べ替えは問題の解決に役立ちました。