Reputation: 12094
I have a small simple code to compare 2 floating point numbers:
I tried using fabs but it gives wrong weird result. What is the mistake, and what is the correct form?
#include <stdio.h>
#include <stdlib.h>
#include <float.h>
void compareFloat(double a1, double a2)
{
if(fabs(a1 - a2) < DBL_EPSILON)
printf("a1 is smaller\n");
else
printf("a1 is larger\n");
}
int main()
{
float a1=0.0000004f, a2=0.0005f;
compareFloat(a1, a2);
}
What is the mistake in this code? It always prints a1 is smaller
even if i set a1=0.004f and a2=0.0005f
Upvotes: 0
Views: 2270
Reputation: 154208
fabs(a1 - a2) < DBL_EPSILON
takes the "floating" out of floating point numbers (FP).
FP numbers are logarithmically distributed. fabs(a1 - a2) < DBL_EPSILON
will always be false for large different numbers, even if a1,a2
are adjacent FP values. fabs(a1 - a2) < DBL_EPSILON
is always true for small FP numbers, even when they differ by many magnitudes of value.
Instead, scale the epsilon.
Compare the 2 numbers into 5 results
void compareFloat(double a1, double a2) {
if(a1 == a2) // Typically not performed is applications, but here for illustration.
printf("a1 is exactly equal to a2\n");
else if(fabs(a1 - a2) <= (DBL_EPSILON *fabs(a1)) )
printf("a1 is nearly equal to a2\n");
else if(a1 < a2)
printf("a1 is smaller than a2\n");
else if(a1 > a2)
printf("a1 is larger than a2\n");
else
printf("a1 is not comparable to a2, at least one of them is a Not-a-Number\n");
}
As others have said, be sure to use fabs()
instead of abs()
.
Upvotes: 3
Reputation: 38173
That is mathematically wrong. You're actually trying to compare if both floats are equal, not larger/smaller.
To compare which one is larger, just use the operator<
, for example like this:
if( abs(a1 - a2) > DBL_EPSILON && a1 < a2 )
// ....
Suppose: a1 == 1.
and a2 == 5.
. Then fabs( a1 - a2 )
will be larger than DBL_EPSILON
, BUT this does not mean, that a1 > a2
.
And the other error is already mentioned - abs
is for int
egers, you need fabs
.
EDIT: I'd create an additional function for comparing floating point numbers, for example:
bool areEqual( double x, double y )
{
return ( fabs( x - y ) < DBL_EPSILON );
}
and then use it directly - will make your code more readable. Example usage:
if( areEqual( a1, a2 ) )
// equal
else if( a1 < a2 ) // here, it's guaranteed, that a1 != a2, so it's safe now
// a1 is smaller
else
// a2 is smaller
Upvotes: 3
Reputation: 234865
The prototype for abs is an integer!
int abs (int number);
You want fabs for floating point
double fabs (double number);
Upvotes: 4