1

我实现了Bruce Dawson提出的AlmostEqual2sComplement ,但用于比较双精度值而不是浮点值。

类似的实现可以在很多地方找到。

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;
}

不幸的是,当比较双精度值 -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是更正版本,其中有一个额外的检查两个浮点数是否具有相反的符号。

于 2012-09-14T09:03:03.200 回答