What is the most effective method for floating and double comparison?

What is the most efficient way to compare two double or two float values?

Simply doing so is not correct:

bool CompareDoubles1 (double A, double B)
{
   return A == B;
}

But similar:

bool CompareDoubles2 (double A, double B) 
{
   diff = A - B;
   return (diff < EPSILON) && (-diff < EPSILON);
}

It seems to be waste disposal.

Does anyone know a smarter floating point comparator?

#1 building

In fact, in digital software, you need to check that two floating-point numbers are exactly equal. I posted on similar issues

https://stackoverflow.com/a/10973098/1447411

Therefore, you cannot say that "CompareDoubles1" is usually wrong.

#2 building

Realize that this is an old topic, but this article is one of the most direct articles I found. If you want to explore more, it also provides a more detailed reference, and the main site covers all problems dealing with floating-point Floating point guide: comparison .

We can“ Floating point tolerance ”Some more practical articles are found in, and it is noted that there are absolute tolerance tests, which can be summed up in C + +:

bool absoluteToleranceCompare(double x, double y)
{
    return std::fabs(x - y) <= std::numeric_limits<double>::epsilon() ;
}

And relative tolerance test:

bool relativeToleranceCompare(double x, double y)
{
    double maxXY = std::max( std::fabs(x) , std::fabs(y) ) ;
    return std::fabs(x - y) <= std::numeric_limits<double>::epsilon()*maxXY ;
}

This paper points out that when x and y are large, absolute tests will fail, while when they are relatively small, relative tests will fail. Assuming that its absolute and relative tolerances are the same, the combined test will be as follows:

bool combinedToleranceCompare(double x, double y)
{
    double maxXYOne = std::max( { 1.0, std::fabs(x) , std::fabs(y) } ) ;

    return std::fabs(x - y) <= std::numeric_limits<double>::epsilon()*maxXYOne ;
}

#3 building

Compare with the ε value compared to what most people do, including in game programming.

You should make some changes to the implementation:

bool AreSame(double a, double b)
{
    return fabs(a - b) < EPSILON;
}

Editor: Christer at In recent blog posts Added a lot of information about this topic. Please enjoy.

#4 building

There is an error in the code you wrote:

return (diff < EPSILON) && (-diff > EPSILON);

The correct code is:

return (diff < EPSILON) && (diff > -EPSILON);

(... Yes, it's different)

I don't know if the Fab won't let you lose your assessment of laziness in some cases. I would say it depends on the compiler. You may want to try both at the same time. If they are equal on average, fab is used.

If you have information about which of the two floats is larger than the other, you can do so in the order of comparison to make better use of delay evaluation.

Finally, you might get better results by inlining this function. Although it is unlikely to improve

Editor: OJ, thank you for correcting your code. So I deleted my comment

#5 building

For a more in-depth approach, read Compare floats . This is the code snippet for the link:

// Usable AlmostEqual function    
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;    
}

Tags: Programming

Posted on Thu, 16 Jan 2020 02:00:17 -0800 by nrerup