简体   繁体   中英

C: Why fabs giving weird result while comparing floating point numbers?

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

The prototype for abs is an integer!

int abs (int number);

You want fabs for floating point

double fabs (double number);

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() .

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM