小数を比較する最良の方法は何ですか?
と のような 2 つの値がある3.45
と3.44
します。それらを確実に比較するための最良の方法は何ですか?
私はすべての数値を345
andとして保存することを考え344
ていたので、整数のみを比較し、小数点のあるユーザーフォーマットの数値のみを表示します。
別の解決策は、カスタム関数を使用して差をテストし、差が0.01
数値よりも小さい場合は等しいはずです。
他に考えられる解決策 (より良い解決策) は何ですか?
小数を比較する最良の方法は何ですか?
と のような 2 つの値がある3.45
と3.44
します。それらを確実に比較するための最良の方法は何ですか?
私はすべての数値を345
andとして保存することを考え344
ていたので、整数のみを比較し、小数点のあるユーザーフォーマットの数値のみを表示します。
別の解決策は、カスタム関数を使用して差をテストし、差が0.01
数値よりも小さい場合は等しいはずです。
他に考えられる解決策 (より良い解決策) は何ですか?
最も一般的な手法は、イプシロンを使用することです (2 番目に説明したこと)。ただし、すべての入力数値に対して適切に機能する一般的なイプシロンを作成することは、非常に困難/不可能な場合があります。0.00001 前後の数値または 1000000000 前後の数値を扱っている場合、0.01 のイプシロンはおそらく恐ろしいものです。イプシロン技術の本当に包括的な分析については、これをお読みください。
あなたが説明した最初の解決策は、時間計算では非常に一般的です。すべてが整数のティック数で表されます。目盛りは、1 秒、1 ミリ秒、または任意のものを表すことができます。その後、必要に応じて別の単位の 10 進数に変換したり、比較したりできます。唯一のことは、ティック サイズを選択する必要があり、1 ティック単位よりも小さいものを表すことはできないということです。
これは「ファジー比較」とも呼ばれ、2 つの値が少し異なる場合があります (許容度、「イプシロン」とも呼ばれます)。通常、このようなイプシロン値は から 程度1E-6
です1E-10
が、小さい値または大きい値の方が適しているアプリケーションが見つかります。この例では、イプシロンは 未満であってはなりません1E-2 = 0.01
。
ニーズに合ったイプシロン値を見つけたら、次のような一連の比較関数を記述できます (C と C++ の共通サブセットで記述されています。マイナーな変更を加えれば、ほとんどすべてのオブジェクト指向/手続き型言語で機能するはずです)。 :
const double fuzzyEpsilon = 1E-6; // just an example!
bool fuzzyEqual(double a, double b) {
return (abs(a - b) <= fuzzyEpsilon);
}
bool fuzzyUnqual(double a, double b) {
return (abs(a - b) > fuzzyEpsilon);
}
int fuzzyCompare(double a, double b) {
return ((a - b) > fuzzyEpsilon) - ((b - a) > fuzzyEpsilon);
}
3 番目の関数は、ファジー比較 ( に類似) を使用して、それぞれ-1
、0
、1
if a < b
、のコードを返します。この実装では、プログラミング言語がブール値を(false) および(true)に暗黙的に変換することを前提としています。そうでない場合は、次を使用します。a == b
a > b
strcmp
0
1
int fuzzyCompare(double a, double b) {
return (a - b) > fuzzyEpsilon ? 1 :
((b - a) > fuzzyEpsilon ? -1 : 0);
}
10進値を2進実数で表すことは概算であり、さまざまな奇妙な動作につながります。精度は、さらに算術演算、特に近くの値を減算すると低下することがよくあります。ただし、個々の値は、比較する前に最小桁数に丸めることにより、比較のためにクリーンアップできます。たとえば、V = round(V * 1e14)/ 1e14は、任意の値Vを10進数の14桁に丸めます。このような2つの値は、同等であるかどうかを自信を持って比較できます。64ビット実数の精度は15.65であるため、14桁(またはそれ以下)に丸めると、エラーの余地があります。
はい、乗算、ラウンド()、除算のシーケンスはコストがかかります。ただし、decimalはヒューマンインターフェイスであり、「面白い」算術を許容できない金融アプリケーションでよく使用されます。間違っていることは、通常、遅いことよりもはるかに悪いことです。