Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C Programming > comparing doubles for equality

Reply
Thread Tools

comparing doubles for equality

 
 
John Smith
Guest
Posts: n/a
 
      12-30-2006
This code for the comparison of fp types is taken from the C FAQ.
Any problems using it in a macro?

/* compare 2 doubles for equality */
#define DBL_ISEQUAL(a,b) (fabs((a)-(b))<=(DBL_EPSILON)*fabs((a)))

Do the same issues involved in comparing 2 fp types for equality
apply to comparing a float to zero? E.g. is if(x == 0.0)
considered harmful?
 
Reply With Quote
 
 
 
 
Tim Prince
Guest
Posts: n/a
 
      12-30-2006
John Smith wrote:
> This code for the comparison of fp types is taken from the C FAQ.
> Any problems using it in a macro?
>
> /* compare 2 doubles for equality */
> #define DBL_ISEQUAL(a,b) (fabs((a)-(b))<=(DBL_EPSILON)*fabs((a)))
>
> Do the same issues involved in comparing 2 fp types for equality
> apply to comparing a float to zero? E.g. is if(x == 0.0) considered
> harmful?

Depending on how you use this, you could make your application highly
dependent on external issues, such as whether you compile for an extra
precision mode, or disable gradual underflow.
 
Reply With Quote
 
 
 
 
Dik T. Winter
Guest
Posts: n/a
 
      12-31-2006
In article <I8Clh.533642$1T2.401780@pd7urf2no> John Smith <(E-Mail Removed)> writes:
> This code for the comparison of fp types is taken from the C FAQ.
> Any problems using it in a macro?
>
> /* compare 2 doubles for equality */
> #define DBL_ISEQUAL(a,b) (fabs((a)-(b))<=(DBL_EPSILON)*fabs((a)))
>
> Do the same issues involved in comparing 2 fp types for equality
> apply to comparing a float to zero? E.g. is if(x == 0.0)
> considered harmful?


If you insert 0.0 for 'a' you will see that the two give precisely the
same result. On the other hand, I think it is possible to construct
two floating point numbers 'a' and 'b', where the result is asymmetric.
But let that not deter you from using the macro, when it is asymmetric
you are in the outskirts of floating-point arithmetic.
--
dik t. winter, cwi, kruislaan 413, 1098 sj amsterdam, nederland, +31205924131
home: bovenover 215, 1025 jn amsterdam, nederland; http://www.cwi.nl/~dik/
 
Reply With Quote
 
Thad Smith
Guest
Posts: n/a
 
      12-31-2006
John Smith wrote:

> This code for the comparison of fp types is taken from the C FAQ.
> Any problems using it in a macro?
>
> /* compare 2 doubles for equality */
> #define DBL_ISEQUAL(a,b) (fabs((a)-(b))<=(DBL_EPSILON)*fabs((a)))


This construction is misleading and I would never use it, because the
implied function, determining whether two doubles are equal, is not an
accurate description of the returned value.

> Do the same issues involved in comparing 2 fp types for equality
> apply to comparing a float to zero? E.g. is if(x == 0.0) considered
> harmful?


Which issues are those? The test "if (x == 0.0)", in contrast, does not
have the inaccurate description that the DBL_ISEQUAL macro does.

In both cases, you should employ good analysis for floating point
comparisons.

--
Thad
 
Reply With Quote
 
CBFalconer
Guest
Posts: n/a
 
      12-31-2006
Tim Prince wrote:
> John Smith wrote:
>
>> This code for the comparison of fp types is taken from the C FAQ.
>> Any problems using it in a macro?
>>
>> /* compare 2 doubles for equality */
>> #define DBL_ISEQUAL(a,b) (fabs((a)-(b))<=(DBL_EPSILON)*fabs((a)))
>>
>> Do the same issues involved in comparing 2 fp types for equality
>> apply to comparing a float to zero? E.g. is if(x == 0.0)
>> considered harmful?

>
> Depending on how you use this, you could make your application
> highly dependent on external issues, such as whether you compile
> for an extra precision mode, or disable gradual underflow.


That's why gcc has the Wfloat-equal switch. As far as the macro is
concerned, the a argument better not have any side effects.

--
Merry Christmas, Happy Hanukah, Happy New Year
Joyeux Noel, Bonne Annee.
Chuck F (cbfalconer at maineline dot net)
<http://cbfalconer.home.att.net>


 
Reply With Quote
 
CBFalconer
Guest
Posts: n/a
 
      12-31-2006
Thad Smith wrote:
> John Smith wrote:
>
>> This code for the comparison of fp types is taken from the C FAQ.
>> Any problems using it in a macro?
>>
>> /* compare 2 doubles for equality */
>> #define DBL_ISEQUAL(a,b) (fabs((a)-(b))<=(DBL_EPSILON)*fabs((a)))

>
> This construction is misleading and I would never use it, because
> the implied function, determining whether two doubles are equal,
> is not an accurate description of the returned value.


How about:

#define DUNEQUAL(a, b) (fabs((a)-(b)) > (DBL_EPSILON)*fabs((a)))

with a caveat against passing an a with side effects.

--
Merry Christmas, Happy Hanukah, Happy New Year
Joyeux Noel, Bonne Annee.
Chuck F (cbfalconer at maineline dot net)
<http://cbfalconer.home.att.net>


 
Reply With Quote
 
Thad Smith
Guest
Posts: n/a
 
      12-31-2006
CBFalconer wrote:
> Thad Smith wrote:
>> John Smith wrote:
>>
>>> This code for the comparison of fp types is taken from the C FAQ.
>>> Any problems using it in a macro?
>>>
>>> /* compare 2 doubles for equality */
>>> #define DBL_ISEQUAL(a,b) (fabs((a)-(b))<=(DBL_EPSILON)*fabs((a)))

>> This construction is misleading and I would never use it, because
>> the implied function, determining whether two doubles are equal,
>> is not an accurate description of the returned value.

>
> How about:
>
> #define DUNEQUAL(a, b) (fabs((a)-(b)) > (DBL_EPSILON)*fabs((a)))
>
> with a caveat against passing an a with side effects.


That misses the point. The only true equality test is given by a==b.
If you need an epsilon, fine, but you should make it explicit.
DBL_EPSILON isn't necessarily the correct choice for a particular
application. In fact, the two tests above may not provide any advantage
over a strict equality.

--
Thad
 
Reply With Quote
 
CBFalconer
Guest
Posts: n/a
 
      12-31-2006
Thad Smith wrote:
> CBFalconer wrote:
>> Thad Smith wrote:
>>> John Smith wrote:
>>>
>>>> This code for the comparison of fp types is taken from the C FAQ.
>>>> Any problems using it in a macro?
>>>>
>>>> /* compare 2 doubles for equality */
>>>> #define DBL_ISEQUAL(a,b) (fabs((a)-(b))<=(DBL_EPSILON)*fabs((a)))
>>> This construction is misleading and I would never use it, because
>>> the implied function, determining whether two doubles are equal,
>>> is not an accurate description of the returned value.

>>
>> How about:
>>
>> #define DUNEQUAL(a, b) (fabs((a)-(b)) > (DBL_EPSILON)*fabs((a)))
>>
>> with a caveat against passing an a with side effects.

>
> That misses the point. The only true equality test is given by
> a==b. If you need an epsilon, fine, but you should make it
> explicit. DBL_EPSILON isn't necessarily the correct choice for a
> particular application. In fact, the two tests above may not
> provide any advantage over a strict equality.


No, I think you miss the point. Floating point is inherently an
approximation, and the above says that anything within the
resolution (i.e. the approximation) is to be considered equal. Any
time you see (a == b) for floating point operands, it is probably a
bug. For example:

for (a = 1.0; a != 0; a -= 0.1) dosomethingwith(a);

will probably not behave. While:

for (a = 1.0; !DUNEQUAL(a, 0.0); a -= 0.1) dosomethingwith(a);

will behave. Of course:

for (a = 1.0; a > 0; a -= 0.1) dosomethingwith(a);

may behave. But it is a crapshoot whether it does an extra cycle.

--
Merry Christmas, Happy Hanukah, Happy New Year
Joyeux Noel, Bonne Annee.
Chuck F (cbfalconer at maineline dot net)
<http://cbfalconer.home.att.net>

 
Reply With Quote
 
SM Ryan
Guest
Posts: n/a
 
      12-31-2006
John Smith <(E-Mail Removed)> wrote:
# This code for the comparison of fp types is taken from the C FAQ.
# Any problems using it in a macro?
#
# /* compare 2 doubles for equality */
# #define DBL_ISEQUAL(a,b) (fabs((a)-(b))<=(DBL_EPSILON)*fabs((a)))
#
# Do the same issues involved in comparing 2 fp types for equality
# apply to comparing a float to zero? E.g. is if(x == 0.0)
# considered harmful?

Floats and doubles use a small number of bits for their values,
so exact equality to zero or any other representable value is
meaningful. Two problems are

(1) most machines do not use radix 10 representation; some decimal
values, such as 0.1 can only be approximated. That means if you
write (x==0.1) you're not really testing x against one tenth but
some other value that is close to one tenth. So the test is not
what you think it is.

(2) many computations with reals are iterative approximations to
an unknown value. Because of the precision limits, they often
cannot reach the exact correct value, so you have to accept when
it is close enough.

--
SM Ryan http://www.rawbw.com/~wyrmwif/
So basically, you just trace.
 
Reply With Quote
 
Dik T. Winter
Guest
Posts: n/a
 
      01-01-2007
In article <(E-Mail Removed)> http://www.velocityreviews.com/forums/(E-Mail Removed) writes:
....
> >> #define DUNEQUAL(a, b) (fabs((a)-(b)) > (DBL_EPSILON)*fabs((a)))

....
> For example:
> for (a = 1.0; a != 0; a -= 0.1) dosomethingwith(a);
> will probably not behave. While:
> for (a = 1.0; !DUNEQUAL(a, 0.0); a -= 0.1) dosomethingwith(a);

you wish to omit the exclamation mark here.
> will behave. Of course:
> for (a = 1.0; a > 0; a -= 0.1) dosomethingwith(a);
> may behave. But it is a crapshoot whether it does an extra cycle.


And now compare the three with:
for (a = 1.0; DUNEQUAL(0.0, a); a -= 0.1) dosomethingwith(a);

A better test would be:

#define DUNEQUAL(a, b) (fabs((a) - (b)) > \
(fabs(a) > fabs(b) ? DBL_EPSILON * fabs(a) : DBL_EPSILON * fabs(b)))

in this way there is no asymmetry.
--
dik t. winter, cwi, kruislaan 413, 1098 sj amsterdam, nederland, +31205924131
home: bovenover 215, 1025 jn amsterdam, nederland; http://www.cwi.nl/~dik/
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
accuracy when comparing doubles vk C++ 23 01-14-2009 09:41 AM
Comparing doubles Thomas Kowalski C++ 28 07-11-2007 07:20 PM
floats doubles long doubles dan C++ 1 11-26-2003 05:12 AM
Comparing two doubles nicolas C++ 3 09-21-2003 09:43 PM
Comparing two floats or doubles to a precision {AGUT2} {H}-IWIK C++ 4 09-12-2003 02:51 PM



Advertisments