Re: comparing doubles for equality



Richard Weeks wrote:
After some hair pulling over the issue of comparing doubles for equality, I came up with this solution based on the notion of relative difference. I'd appreciate your comments.

There is nothing wrong with comparing doubles to see if they are close
to each other, but it is not the same thing as comparing whether they
are equal. It would be less confusing if you called it something other
than equality.

Also, of course, be aware that round-off error is the real problem, and
for this approach to work right, you have to have some way of ensuring
that your computations don't accumulate more round-off error than your
margin allows for. That is not necessarily an easy problem.

#define MAXRELDIFF .000000000001

/* compare doubles for equality. First compare
integer parts; if they are unequal, return
false. If they are equal, calculate relative
difference of fractional parts and compare
it to a tolerance. */
int dbl_isequal(double a, double b)
{
double fraca, fracb, reldiff;
if((int)a == (int)b)
{
fraca = a - (int)a;
fracb = b - (int)b;
reldiff = rel_diff(fraca, fracb);
if(reldiff > MAXRELDIFF) return 0;
else return 1;
}
return 0;
}

I don't see why it's useful to compare only the fractional parts. These
are floating point types, so the fractional part will have different
precision depending on the integer part! In fact, for really large
numbers, the loss of precision could easily go into the integer part
of the number.

It seems like, if anything, you want the tolerance to be relative to
the magnitude of the numbers. That's what the round-off error is
relative to (for simple types of computations).

Therefore, it seems like this would be an improvement:


#define TOLERANCE 0.000000001

int dbl_isequal(double a, double b)
{
if (a < b * (1 - TOLERANCE)) return 0;
if (a > b * (1 + TOLERANCE)) return 0;
return 1;
}

Or something that has a little more symmetry:

#defined TOLERANCE 0.000000001

int dbl_isequal(doube a, double b)
{
if (a < b * (1 - TOLERANCE)) return 0;
if (b < a * (1 - TOLERANCE)) return 0;
return 1;
}

c > d ? c : d;

I don't know what this line is supposed to do. :-)

- Logan
.



Relevant Pages

  • Re: comparing doubles for equality
    ... /* compare doubles for equality. ... if(reldiff> MAXRELDIFF) return 0; ... useful to calculate the relative difference separately. ...
    (comp.programming)
  • Re: comparing doubles for equality
    ... /* compare doubles for equality. ... if(reldiff> MAXRELDIFF) return 0; ... useful to calculate the relative difference separately. ...
    (comp.programming)
  • comparing doubles for equality
    ... After some hair pulling over the issue of comparing doubles for equality, I came up with this solution based on the notion of relative difference. ... double fraca, fracb, reldiff; ...
    (comp.programming)
  • Re: collection framework: using the good interface
    ... The word object's class would implement Comparable, and should have equals and hashCode consistent with compareTo, but I would not make two words equal unless they are, in all respects, the same word. ... I'm more and more convinced that equality should involve all aspects of the Word class, but I'm still uncomfortable with mixing lexicographic information (allowing to compare objects in different collections) and information about frequency, distribution, cooccurrents. ...
    (comp.lang.java.help)
  • Re: If statement
    ... i want to compare atabsin equality ... or call the function atabs passing in the argument i ... since that value is *not* non-zero, ...
    (comp.soft-sys.matlab)