Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

If operator< works properly for floating-point types, why can't we use it for equality testing?

Properly testing two floating-point numbers for equality is something that a lot of people, including me, don't fully understand. Today, however, I thought about how some standard containers define equality in terms of operator<. I always see people with problems surrounding equality, but never with the other relational comparisons. There are even silent versions of them to use, which include everything except for equality and inequality.

Assuming operator< works "properly", unlike operator==, why couldn't we do this:

bool floateq(float a, float b) {
    //check NaN
    return !(a < b) && !(b < a);
}

In fact, I did run a test with an additional overload for doubles, as seen here, and it seems to have the same pitfalls as comparing them with operator==:

std::cout << "float->double vs double: " 
          << floateq(static_cast<double>(0.7f), 0.7) << " " 
          << (static_cast<double>(0.7f) == 0.7) << "\n";

Output:

float->double vs double: 0 0

Am I to worry about using all comparison operators, or is there some other aspect of comparing floating-point numbers that I'm not understanding correctly?

like image 282
chris Avatar asked Jul 15 '13 20:07

chris


People also ask

Why should we not use floating point numbers for equality?

This is because floating point values are not precise, and small rounding errors in the floating point operands may cause unexpected results.

Should you use the == operator to determine whether objects of type float are equal?

09. Should you use the == operator to determine whether objects of type float are equal? Nope, not a good idea.

How should one test for equality with floating point numbers?

Floating point numbers should be considered equal if their difference is within an appropriate margin of error.

Is it safe to use the == operator for verifying is two float variables are equal?

a == b means " a is equal to b ". It is not safe (because it is not correct) to expect that the result of some calculation will be zero in double (or more generally, floating point) arithmetics whenever the result of the same calculation in pure Mathematics is zero.


1 Answers

The ==, <, >, <=, >=, and != operators work just fine with floating-point numbers.

You seem to have the premise that some reasonable implementation of < ought to compare (double)0.7f equal to 0.7. This is not the case. If you cast 0.7f to a double, you get 0x1.666666p-1. However, 0.7 is equal to 0x1.6666666666666p-1. These are not numerically equal; in fact, (double)0.7f is considerably smaller than 0.7 --- it would be ridiculous for them to compare equal.

When working with floating-point numbers, it is important to remember that they are floating-point numbers, rather than real numbers or rational numbers or any other such thing. You have to take into account their properties and not the properties everyone wants them to have. Do this and you automatically avoid most of the commonly-cited "pitfalls" of working with floating-point numbers.

like image 65
tmyklebu Avatar answered Sep 22 '22 03:09

tmyklebu