Let\'s say I have two floating point numbers, and I want to compare them. If one is greater than the other, the program should take one fork. If the opposite is true, it should
The IEEE 754 (floating point) standard states that addition or subtraction can result in a positive or negative infinity, so b + FLOAT_EPSILON and b - FLOAT_EPSILON can result in positive or negative infinity if b is FLT_MAX or -FLT_MAX. The floating point standard also states that infinity compares as you would expect, with FLT_MAX < +infinity returning true and -FLT_MAX > -infinity.
For a closer look at the floating point format and precision issues from a practical standpoint, I recommend taking a look at Christer Ericson's book Real Time Collision Detection or Bruce Dawson's blog posts on the subject, the latest of which (with a nice table of contents!) is at http://randomascii.wordpress.com/2013/02/07/float-precision-revisited-nine-digit-float-portability/.
If you can guarantee that a
and b
are not NaNs or infinities, then you can just do:
if (a<b) {
…
} else {
…
}
The set of all floating point values except for infinities and NaNs comprise a total ordering (with a glitch with two representations of zero, but that shouldn't matter for you), which is not unlike working with normal set of integers — the only difference is that the magnitude of intervals between subsequent values is not constant, like it is with integers.
In fact, the IEEE 754 has been designed so that comparisons of non-NaN non-infinity values of the same sign can be done with the same operations as normal integers (again, with a glitch with zero). So, in this specific case, you can think of these numbers as of “better integers”.
What about less than check with an epsilon window ? if a is less than b then a can not be equal to b
/**
* checks whether a <= b with epsilon window
*/
template <typename T>
bool eq(T a, T b){
T e = std::numeric_limits<T>::epsilon();
return std::fabs(a-b) <= e;
}
/**
* checks whether a < b with epsilon window
*/
template <typename T>
bool lt(T a, T b){
if(!eq(a,b)){ // if a < b then a != b
return a < b;
}
return false;
}
/**
* checks whether a <= b with epsilon window
*/
template <typename T>
bool lte(T a, T b){
if(eq(a,b)){
return true;
}
return a < b;
}
Short answer, it is guaranteed never to be called.
If a<b
then a will always be less than b plus a positive amount, however small. In which case, testing if a is less than b + an amount will be true.
The third case won't get reached.
Tests for inequality are exact, as are tests for equality. People get confused because they don't realize that the values they are working with might not be exactly what they think they are. So, yes, the comment on the final function call is correct. That branch will never be taken.