59

http://msdn.microsoft.com/en-us/library/system.double.epsilon.aspx

2 つの浮動小数点数が等しいと見なされるかどうかを判断するカスタム アルゴリズムを作成する場合は、Epsilon 定数よりも大きい値を使用して、2 つの値が等しいと見なされる許容可能な差の絶対マージンを確立する必要があります。(通常、その差のマージンは Epsilon の何倍も大きくなります。)

では、これは実際には比較に使用できるイプシロンではないのでしょうか? MSDN の文言がよくわかりません。

ここの例でイプシロンとして使用できますか? - float と double の比較で最も効果的な方法は何ですか?

そして最後に、これは非常に重要だと思われるので、等しい、より大きい、より小さい、より小さいか等しい、より大きいか等しいの確実な実装があることを確認したいと思います。

4

9 に答える 9

87

彼らがそれを書いたとき、彼らが を吸っていたのか私にはわかりません。Double.Epsilon0 ではない、表現可能な非正規化浮動小数点値の最小値です。知っていることは、切り捨てエラーが発生した場合、常にこの値よりも大きくなるということだけです。はるかに大きいです。

タイプは、System.Double最大 15 桁までの正確な値を表すことができます。したがって、double 値xが何らかの定数に等しい場合の単純な一次推定は、定数 * 1E-15 のイプシロンを使用することです。

public static bool AboutEqual(double x, double y) {
    double epsilon = Math.Max(Math.Abs(x), Math.Abs(y)) * 1E-15;
    return Math.Abs(x - y) <= epsilon;
}

ただし、切り捨てエラーが蓄積する可能性があることに注意する必要があります。xとの両方yが計算値である場合は、イプシロンを増やす必要があります。

于 2010-03-09T18:50:05.487 に答える
50

等しい、より大きい、より小さい、より小さいか等しい、より大きいか等しいの確実な実装があることを確認したいと思います。

2 進浮動小数点演算を使用しています。

2 進浮動小数点演算は、長さ、質量、電荷、時間などの物理量を表すために設計されました。

おそらく、使用が意図されていたとおりにバイナリ浮動小数点演算を使用しています。つまり、物理量の演算を行うためです。

物理量の測定には、測定に使用されるデバイスの精度に応じて、常に特定の精度があります。

あなたが操作している量の値を提供するのはあなたなので、その量の「エラーバー」が何であるかを知っているのはあなたです. たとえば、「建物の高さは 123.56 メートル」という数量を提供している場合、これはセンチメートルまでは正確ですが、マイクロメートルまでは正確ではないことがわかります。

したがって、2 つの量が等しいかどうかを比較する場合、望ましいセマンティクスは、「これら 2 つの量は、各測定値で指定された誤差範囲内で等しいか?」ということです。

これで、あなたの質問に対する答えが得られました。あなたがしなければならないことは、各数量のエラーが何であるかを追跡することです。たとえば、建物の高さは「123.56 メートルの 0.01 以内」です。それが測定の正確さであることがわかっているからです。その後、別の測定値 123.5587 が得られ、2 つの測定値が誤差許容範囲内で「等しい」かどうかを知りたい場合は、減算を行い、誤差許容範囲内にあるかどうかを確認します。この場合はそうです。測定値が実際にマイクロメートル単位で正確である場合、それらは等しくありません。

要するに、あなたが操作している数字がどこから来たのかを最初に知っているのはあなただけだからです。製造に使用した機器の精度を考慮して、測定に適した許容誤差を使用してください。

于 2010-03-09T19:06:47.160 に答える
12

1.0に近い2つのdouble値があるが、それらの最下位ビットのみが異なる場合、それらの差はDouble.Epsilonよりも桁違いに大きくなります。実際、違いは小数点以下324桁です。これは、指数部分の影響によるものです。Double.Epsilonには大きな負の指数がありますが、1.0の指数はゼロです(もちろん、バイアスが削除された後)。

2つの類似した値が等しいかどうかを比較する場合は、比較する値の桁数に適したカスタムイプシロン値を選択する必要があります。

比較しているdouble値が1.0に近い場合。その場合、最下位ビットの値は0.0000000000000001に近くなります。比較しているdouble値がクアドリリオンにある場合、最下位ビットの値は1000にもなる可能性があります。これらの状況の両方で、イプシロンの単一の値を同等性の比較に使用することはできません。

于 2010-03-09T18:21:53.030 に答える
6

私はちょうどこれをしました-ケントボガーツのアイデアを使用して。

private bool IsApproximatelyEqual(double x, double y, double acceptableVariance)
{
     double variance = x > y ? x - y : y - x;
     return variance < acceptableVariance;

     //or
     //return Math.Abs(x - y) < acceptableVariance;
}
于 2012-01-05T11:34:58.543 に答える
4

2 つの値が正確に等しいか、double 型の表現可能な差が最小であることを確認する場合は、比較に使用できます。double.Epsilon一般的に言えば、 2 つの double がほぼ等しいかどうかを確認するには、より大きい数値を使用する必要があります。

.NET フレームワークが次のようなものを定義しない理由

bool IsApproximatelyEqual(double value, double permittedVariance);

私を超えています。

于 2010-03-09T18:13:21.970 に答える
1

ダブルスを比較する際の問題は、等しいが丸め誤差のために同じ値に評価されていない2つの異なる数学結果を比較すると、多少の違いが生じることです...これはイプシロンよりも大きくなります、エッジケースを除く。また、信頼できるイプシロン値を使用することも困難です。静的な最小差イプシロンを使用すると、ダブル自体が高いまたは低いときに差が小さすぎるか大きすぎる可能性があるため、2つのダブルの差がパーセンテージ値未満の場合は2つのダブルが等しいと考える人もいます。

于 2010-03-09T18:23:46.583 に答える
1

以下は、Silverlight コントロール ツールキット内に 2 回含まれているコードの一部です。

    public static bool AreClose(double value1, double value2)
    {
        //in case they are Infinities (then epsilon check does not work)
        if(value1 == value2) return true;
        // This computes (|value1-value2| / (|value1| + |value2| + 10.0)) < DBL_EPSILON
        double eps = (Math.Abs(value1) + Math.Abs(value2) + 10.0) * DBL_EPSILON;
        double delta = value1 - value2;
        return(-eps < delta) && (eps > delta);
    }

ある場所では1e-6、イプシロンに使用されます。別の彼らが使用します1.192093E-07。独自のイプシロンを選択する必要があります。

于 2010-03-09T19:26:15.623 に答える
0

自分で計算するか、独自の定数を定義する必要があります。

double calculateMachineEpsilon() {
    double result = 1.0;
    double one = 1.0/256;

    while(one + result/2.0 != 1.0) {
        result/=2.0;
    }
    return result;
}
于 2014-08-12T10:08:05.973 に答える