Re: comparing doubles for equality
- From: Bjørn Augestad <boa@xxxxxxxxxxxxxx>
- Date: Sun, 29 Apr 2007 22:06:56 +0200
Logan Shaw wrote:
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;
}
Here's how I do it (more or less):
#define TOLERANCE 0.0000001
int dbl_isequal(double a, double b)
{
return (fabs(a - b) < TOLERANCE) ? 1 : 0;
}
Works for me.
Bjørn
.
- Follow-Ups:
- Re: comparing doubles for equality
- From: Logan Shaw
- Re: comparing doubles for equality
- References:
- comparing doubles for equality
- From: Richard Weeks
- Re: comparing doubles for equality
- From: Logan Shaw
- comparing doubles for equality
- Prev by Date: Re: comparing doubles for equality
- Next by Date: Re: comparing doubles for equality
- Previous by thread: Re: comparing doubles for equality
- Next by thread: Re: comparing doubles for equality
- Index(es):
Relevant Pages
|