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?
This is because floating point values are not precise, and small rounding errors in the floating point operands may cause unexpected results.
09. Should you use the == operator to determine whether objects of type float are equal? Nope, not a good idea.
Floating point numbers should be considered equal if their difference is within an appropriate margin of error.
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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With