我正在移植一些比较浮点数以处理64位 double 数而不是32位浮点数的代码,但是我对代码中使用的一些魔术数字感到有些困惑。

资料来源:http://www.cygnus-software.com/papers/comparingfloats/comparingfloats.htm

这是代码:

bool AlmostEqual2sComplement(float A, float B, int maxUlps)
{
    // 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);
    int aInt = *(int*)&A;
    // Make aInt lexicographically ordered as a twos-complement int
    if (aInt < 0)
        aInt = 0x80000000 - aInt;
    // Make bInt lexicographically ordered as a twos-complement int
    int bInt = *(int*)&B;
    if (bInt < 0)
        bInt = 0x80000000 - bInt;
    int intDiff = abs(aInt - bInt);
    if (intDiff <= maxUlps)
        return true;
    return false;
}

问题:

困扰我的主要是断言中的4 * 1024 * 1024号。这代表什么?对于64位双打,此值是什么?两者会一样吗?
0x80000000幻数也用作负零浮点数的int表示。所以我猜要64位 double ,这将不得不增加到0x8000000000000000吗?

最佳答案

Ewww。

4 * 1024 * 1024是22位,比浮点数的显式尾数位少1。我认为两倍的等效值为2 ** 51。

您对0x800是正确的...此代码依赖于以下事实:可以比较IEEE浮点数,就好像它们是使用符号和幅度表示的整数一样。

当然,这段代码充满了不确定的行为。更不用说讨厌,野蛮和矮小了。

10-08 08:55