473,396 Members | 2,014 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,396 software developers and data experts.

comparing doubles for equality

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?
Dec 30 '06 #1
12 6823
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.
Dec 30 '06 #2
In article <I8Clh.533642$1T2.401780@pd7urf2noJohn Smith <JS****@mail.netwrites:
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/
Dec 31 '06 #3
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
Dec 31 '06 #4
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>
Dec 31 '06 #5
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>
Dec 31 '06 #6
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
Dec 31 '06 #7
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>

Dec 31 '06 #8
John Smith <JS****@mail.netwrote:
# 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.
Dec 31 '06 #9
In article <45***************@yahoo.comcb********@maineline.net 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/
Jan 1 '07 #10
CBFalconer wrote:
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);
While I agree that this is likely to fail ...
for (a = 1.0; !DUNEQUAL(a, 0.0); a -= 0.1) dosomethingwith(a);
.... there is no guarantee that this second form is correct, for the
definition supplied above. Why? Because each subtraction may invoke a
roundoff. After several roundings, you maybe off by more than one lsb
for a number with the magnitude of 1, let alone, say, one lsb of 1e-7.

Note also that DUNEQUAL, is not commutative, which is fails the
principle of least astonishment.
>
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, to make it robust, you could do

for (a = 1.0; a 0.1/2; a -= 0.1) dosomethingwith(a);

or, to use the best approximation of of each nominal value of a:

int i;
for (i = 10; i 0; i--) { dosomethingwith (i*0.1); }

or, for the pragmatic types

for (a = 10; a 0; a -= 1) dosomethingwith (a/10);

The last form is not guaranteed, but performs correctly on any floating
point system I am familiar with, except maybe logarithmic systems, due
to the limited number of bits required to exactly represent the integer
values.

--
Thad
Jan 1 '07 #11
"Dik T. Winter" wrote:
cb********@maineline.net 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.
Not needed. The use of epsilon is only needed when a and b are
nearly equal, thus either can be used to derive it. The problem of
a zero remains, and ties in with the use of extremely small
operands in general. To handle all these cases we probably should
use a function rather than a macro.

--
Merry Christmas, Happy Hanukah, Happy New Year
Joyeux Noel, Bonne Annee.
Chuck F (cbfalconer at maineline dot net)
<http://cbfalconer.home.att.net>
Jan 1 '07 #12
CBFalconer wrote:
>
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.
I disagree.
It really all depends
on what you're doing with the floating point values.
If you're using qsort to sort an array of doubles,
then there's really no place for DBL_EPSILON in your compar function.

int compar(const void *arg1, const void *arg2)
{
return *(double *)arg2 *(double *)arg1 ? -1
: *(double *)arg2 != *(double *)arg1;
}

--
pete
Jan 3 '07 #13

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

5
by: inquirydog | last post by:
Hi- Does anyone know a way to compare whether two nodes contain the same information in xslt (the name, attributes, and all content recursivly should be the same. I am interested in the case...
19
by: Dennis | last post by:
I have a public variable in a class of type color declared as follows: public mycolor as color = color.Empty I want to check to see if the user has specified a color like; if mycolor =...
12
by: barcaroller | last post by:
Is it legal to compare the contents of two multi-field variables (of the same struct) using "==" and "!="? struct { int a; int b; } x,y; ...
6
by: utab | last post by:
Hi there, I would like to compare the values in two vectors of double. I can do it by using iterators, I had an idea but wondering there is a library facility to do that. vector<double> a;...
6
by: Edward Diener | last post by:
Now that operator overloading allows to ref classes to be compared for equality using == syntax, how does one compare the actual ref pointers ( ^ ) for equality instead ? As an example: ...
20
by: Bill Pursell | last post by:
This question involves code relying on mmap, and thus is not maximally portable. Undoubtedly, many will complain that my question is not topical... I have two pointers, the first of which is...
25
by: J Caesar | last post by:
In C you can compare two pointers, p<q, as long as they come from the same array or the same malloc()ated block. Otherwise you can't. What I'd like to do is write a function int comparable(void...
27
by: Thomas Kowalski | last post by:
Hi everyone, To determine equality of two doubles a and b the following is often done: bool isEqual ( double a, double b ) { return ( fabs (a-b) < THRESHOLD ); } But this a approach usually...
18
by: eman.abu.samra | last post by:
Hi all, i have encountered the strangest behavior. Check out this simple program: #include <stdio.h> int main() { double time = 1;
0
by: ryjfgjl | last post by:
In our work, we often receive Excel tables with data in the same format. If we want to analyze these data, it can be difficult to analyze them because the data is spread across multiple Excel files...
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...
0
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows...
0
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each...
0
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing,...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.