我实现了Bruce Dawson建议的AlmostEqual2sComplement,但是用于比较double而不是float值。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;
}
不幸的是,当比较double值-1.0和4.0时,函数返回true。 这是因为在这种情况下,intDiff结果等于0x8000000000000000
和 的0x8000000000000000
绝对值再次0x8000000000000000
我目前的解决这个问题是不是采取intDiff的绝对值,而是改变intDiff的对比和maxUlps到:
if (intDiff <= maxUlps && -maxUlps <= intDiff)
return true;
必须有更多的(也许不那么明显)的情况下intDiff结果0x8000000000000000
。
我想知道AlmostEqual2sComplement的其他实现是否只是不知道这个问题,或者如果我在我的原始实现中犯了一个错误?
谢谢,太棒了。这解决了问题!由于如果符号aInt和bInt相等,intDiff不会产生下溢。 –