我按照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的其他实现没有意识到这个问题,或者我在最初的实现中犯了一个错误?
发布于 2012-09-14 17:03:03
这里的http://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition是修正后的版本,这里有一个额外的检查两个浮点数是否有相反的符号。
https://stackoverflow.com/questions/12420528
复制相似问题