Regardless of the way you compare floating point numbers for equality, make sure that other comparison operators are consistent with behavior of your equal
operator.
In case of <
you need to guarantee that !(a < b) && !(b < a)
is the same as a == b
.
Let's say, you implemented the following equal
function:
const double EPSILON = 10e-8;
bool equal(double a, double b)
{
return fabs(a - b) < EPSILON;
}
It is not always safe to use <
operator, because it may get inconsistent result.
See
double a = 0.1 + 0.2;
double b = 0.3;
equal(a, b); // true
a < b; // false
b < a; // TRUE
See, both b < a
and equal(a, b)
return true
, and this is semantically incorrect.
The easiest way is to use your equal
function to define less
:
bool less(double a, double b)
{
return a < b && !equal(a, b);
}
Now, it is consistent
double a = 0.1 + 0.2;
double b = 0.3;
equal(a, b); // true
less(a, b); // false
less(b, a); // false
Use the same approach to define other operations (like greater
, lessOrEq
etc.). Such consistency will let you to avoid a bunch of subtle bugs in practice.