我移植了一些代码,用于比较浮点数以处理64位双精度而不是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位双打,这必须增加到0x8000000000000000
?
答案 0 :(得分:2)
EWWW。
4 * 1024 * 1024是22位,比浮点数的显式尾数位数少一个。我想,等于双倍的是2 ** 51。
你对0x800是正确的......这段代码依赖于这样一个事实,即可以将IEEE浮点数进行比较,就好像它们是使用符号和幅度表示的整数一样。
当然,这段代码充满了未定义的行为。更不用说讨厌,野蛮和短暂。