LabWindows/CVI

cancel
Showing results for 
Search instead for 
Did you mean: 

Comparison of equal doubles fails

Hello,
 
can somebody explain the curious behaviour which can bee seen on the attached screenshot to me?
 
I try to compare two doubles of the same value, but the comparison fails.
 
Thanks
0 Kudos
Message 1 of 8
(5,571 Views)
you should _never_ compare double's for exact equality.
in your example, just switch representation for variables to scientific.
then you can see the values differ slightly (which is quit normal in this case).
see attached screenshot.

--
Once the game is over, the king and the pawn go back into the same box.
0 Kudos
Message 2 of 8
(5,550 Views)
Thanks for your answer, exactly the info I was hoping to get.
0 Kudos
Message 3 of 8
(5,545 Views)
you're welcome 🙂

btw., I usually use something like:

    double a,b,eps=1e-15;
    a=0.1;
    b=((0.1-.09)/0.1);
    if (fabs(a-b) < eps)
        printf("equal");
    else
        printf("unequal");

for double comparisons.
--
Once the game is over, the king and the pawn go back into the same box.
0 Kudos
Message 4 of 8
(5,539 Views)
In message <1163587214704-441277@exchange.ni.com>, MaWie <x@no.email>
writes
>Hello,
>&nbsp;
>can somebody explain the curious behaviour which can bee seen on the
>attached screenshot to me?
>&nbsp;
>I try to compare two doubles of the same value, but the comparison fails.
>&nbsp;
>Thanks
>
>
>Snapshot_CompEqual.jpg:
>http://forums.ni.com/attachments/ni/180/26276/1/Snapshot_CompEqual.jpg

You cannot compare floating point variables in the same way as integers.

Although the values of a and b appear to be the same, they are minutely
different. You can see the individual bytes in a double by using the
following union;

union double2uchar{
double d;
unsigned char uc[8];
} union_a, union_b;

Then;
union_a.d = 0.1;
union_b.d = ( (0.1 - 0.09) / 0.1);

In a watch window;
union_a.uc[0 - 7] = 154, 153, 153, 153, 153, 153, 185, 63
union_b.uc[0 - 7] = 160, 153, 153, 153, 153, 153, 185, 63

Very clearly not the same.

To do this correctly you should subtract a from b and compare the
absolute result to a very small (non zero) number.

E.G.

if( 0.00000001 > fabs( a - b ) ){
// Unequal.
}

The Programmers Toolbox has a function for this;

FP_Compare (a, b);

--
Regards,

John Cameron.
Type softly, read gently.
0 Kudos
Message 5 of 8
(5,531 Views)

Thanks for your reply, John Cameron,

I did not know about the FP_Compare function. I find it very useful (and also the other FP_... -functions in the toolbox library).

0 Kudos
Message 6 of 8
(5,485 Views)

Hi Mawie,

All advices that have already been given to you are true ! The exact explanation of all this is the way your machine codes numbers (floating points). Just have a look at this link here.

Regards,

0 Kudos
Message 7 of 8
(5,467 Views)

For very small numbers or very large numbers, comparing the difference of two floats to a constant can cause problems.  I compare the ratios of the two numbers and allow a small tolerance of a variation from 1.0.  Reviewing the function help info for the FP_Compare in the Programmer's Toolbox shows that function also looks at a ratio.

Here's a sample more portable than FP_Compare.

#include <ansi_c.h>

#define FP_X_EQ_Y 0
#define FP_X_LT_Y -1
#define FP_X_GT_Y 1

int float_compare(double x, double y);

main()
{
 double x, y;
 int i, j;
 int equals = 0;
 int closeenough = 0;
 int compared = 0;
 
 // generate some numbers for comparison
 for (i=1; i<30; i++)
 {
  compared++;
  x = pow(3.1459, i);
  y = 1.0;
  
  for (j=1; j<=i; j++)
   y *= 3.1459;

  if (x==y)
  {
   printf("equals\n");
   equals++;
  }
  else
   printf("%.10f - %.10f = %.10f\n", x, y, x-y);
   
  if (float_compare(x, y) == FP_X_EQ_Y)
  {
   printf("close enough\n");
   closeenough++;
  }
 }

 // compare a common example of float inequality
 x = 0.1;
 y = (0.1 - 0.09)/0.1;
 compared++;
 
 if (x==y)
 {
  printf("equals\n");
  equals++;
 }
 else
  printf("%.10f - %.10f = %.10f\n", x, y, x-y);
  
 if (float_compare(x, y) == FP_X_EQ_Y)
 {
  printf("close enough\n");
  closeenough++;
 }
 
 printf( "%d compared\n"
   "%d equal\n"
   "%d close enough\n",
   compared, equals, closeenough);
}

/******* float_compare ******************
* compares two floating point numbers within a tolerance.
* compares ratios so it will work on small numbers.
* return values are similar to those in strcmp:
* 0 if equal (within the tolerance)
* -1 if x < y
* +1 if x > y
*****************************************/
int float_compare(double x, double y)
{
 double float_tolerance = 1e-9;
 double ratio;
 
 ratio = x/y;
 if (ratio < 1-float_tolerance)
  return FP_X_LT_Y;
 else if (ratio > 1+float_tolerance)
  return FP_X_GT_Y;
 else
  return FP_X_EQ_Y;

}

0 Kudos
Message 8 of 8
(5,371 Views)