1

Bruce Dawsonによって提案されたように、AlmostEqual2sComplement を実装しましたが、float 値ではなく double 値を比較するためです。

同様の実装が多くの場所で見られます。

bool AlmostEqual2sComplement(double A, double B, int maxUlps= 10)
{
    // Make sure maxUlps is non-negative and small enough that the
    // default NAN won't compare as equal to anything.
    // assert maxUlps > 0 && maxUlps < 4 * 1024 * 1024;

    long long aInt = *(long long*)&A;
    // Make aInt lexicographically ordered as a twos-complement int
    if (aInt < 0)
        aInt = 0x8000000000000000 - aInt;

    // Make bInt lexicographically ordered as a twos-complement int
    long long bInt = *(long long*)&B;
    if (bInt < 0)
        bInt = 0x8000000000000000 - bInt;

    long long intDiff = aInt - bInt;
    if (intDiff < 0)
        intDiff= intDiff*-1;

    if (intDiff <= maxUlps)
        return true;
    return false;
}

残念ながら、double 値 -1.0 と 4.0 を比較すると、関数は true を返します。これは、この場合 intDiff の結果が等しく0x8000000000000000なり、の絶対値0x8000000000000000が再びになるためです。0x8000000000000000

この問題に対する私の現在の解決策は、intDiff の絶対値を取るのではなく、intDiff と maxUlps の比較を次のように変更することです。

if (intDiff <= maxUlps && -maxUlps <= intDiff)
    return true;

intDiff の結果が0x8000000000000000.

私は、AlmostEqual2sComplement の他の実装がこの問題を認識していないだけなのか、それとも元の実装で間違いを犯したのか疑問に思っています。

4

1 に答える 1

1

ここhttp://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-editionは修正版で、2 つの float の符号が反対かどうかの追加チェックがあります。

于 2012-09-14T09:03:03.200 に答える