4

最初は最大の相対差だけに頼れると思っていましたが、間違っていました。たとえば、、、の場合a = 0.0b = 0.5それらの相対的な差は1.0です。この場合approxEquals(lhs, rhs, maxRelDiff, maxAbsDiff)、2つの浮動小数点数が等しいかどうかを判断するために、最大絶対差に依存します。

2つの質問は次のとおりです。

  1. デフォルト(1e-2、1e-5)が十分に正確でない場合、どうすれば新しい最大相対差と絶対差のペアを思い付くことができますか?デフォルト値としてどのように1e-2選択されましたか?1e-5たとえば1e-4、最大相対差として選択した場合、最大絶対差はどれくらいですか?

  2. floatsとを正しく機能させるために、最大相対差と絶対差の値を調整するにはどうすればよいdoublesですか?

4

2 に答える 2

1

ソースコードをチェックすると、これが得られます(範囲の実装を切り取りました)

bool approxEqual(T, U, V)(T lhs, U rhs, V maxRelDiff, V maxAbsDiff = 1e-5)
{   

    if (rhs == 0)
    {
        return fabs(lhs) <= maxAbsDiff;
    }
    static if (is(typeof(lhs.infinity)) && is(typeof(rhs.infinity)))
    {
        if (lhs == lhs.infinity && rhs == rhs.infinity ||
            lhs == -lhs.infinity && rhs == -rhs.infinity) return true;
    }
    return fabs((lhs - rhs) / rhs) <= maxRelDiff
        || maxAbsDiff != 0 && fabs(lhs - rhs) <= maxAbsDiff;
}

この最後の行は、調査する必要があるものです。

return fabs((lhs - rhs) / rhs) <= maxRelDiff
        || maxAbsDiff != 0 && fabs(lhs - rhs) <= maxAbsDiff;

言い換えると、数値がの係数以下で相対的にmaxRelDiff異なっている場合、または絶対的に以下で異なっている場合、関数は true を返します。maxAbsDiff

したがって、maxRelDiffof 0.01(または1E-2) を使用すると、2 (10 進数) 桁の精度と比較されます

また、difficient from 0を使用するmaxAbsDiffと、相対差が 0 より大きい場合でも、0 に近い数値を等しいと見なすことができます。maxRelDiff

編集:基本的に、最初に比較がどれだけ正確である必要があるかmaxRelDiffを決定し、それに基づいて選択し、次にどの時点で数値が0に等しいかを決定します

コメントの例で:

approxEqual(1+1e-10, 1.0, 1e-10, 1e-30) 
approxEqual(1+1e-10, 1.0, 1e-9, 1e-30)

これは 1 に近い値を比較するため、maxRelDiffここでは切り札であり、maxAbsDiff(より小さいmaxRelDiff) を選択しても何も変わりません。

approxEqual(0, 1e-10, 1e-10, 1e-30) 
approxEqual(0, 1e-9, 1e-9, 1e-30)

これは 0 に近い値を 0 と比較するため、RelDiff ( fabs((lhs - rhs) / rhs)) は 1 になり、maxAbsDiff切り札になります。

于 2012-01-02T03:54:54.980 に答える
0

元の質問には答えられませんが、個人的にfabsは浮動小数点の比較に使用します。

return fabs(f1 - f2) < 0.10;
于 2012-01-02T02:27:44.353 に答える