473,387 Members | 1,578 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,387 software developers and data experts.

Equality of floating-point numbers (special case)

Hi guys,

I'm sure this has been beaten to death on this newsgroup, but I can't
find it in the CLC FAQ.

Consider the following code:

--------

double x = some_value_from_somewhere;
double y = x;

if ((x == y) && ((x - y) == 0)) {
puts("This is what I want");
}

--------

Will the condition in the if statement always, unconditionally, and
portably evaluate to a true value?

I know that I normally cannot rely on testing floats for equality; I
just wonder if this holds also when the variables in question are
explicitly set to the same value in the source.

I feel a bit stupid even typing this question since I can't imagine how
x and y could possibly come out as unequal by any implementation's
standard, but since I've been bitten quite a few times by things that
seemed obvious but turned out to be different (for, in retrospect, very
sensible reasons) I feel that I'd rather ask.

Thanks,
robert
Apr 19 '06 #1
14 2585


Robert Latest wrote On 04/19/06 10:06,:
Hi guys,

I'm sure this has been beaten to death on this newsgroup, but I can't
find it in the CLC FAQ.

Consider the following code:

--------

double x = some_value_from_somewhere;
double y = x;

if ((x == y) && ((x - y) == 0)) {
puts("This is what I want");
}

--------

Will the condition in the if statement always, unconditionally, and
portably evaluate to a true value?


No. The Standard permits floating-point implementations
that support the notion of "not a number," or NaN. In IEEE
implementations, NaN is unequal to all floating-point values,
including itself (so `x == y' is false) and most ordinary
arithmetic operations with NaN operands yield a NaN result
(so `x - y' is NaN and `x - y == 0' is false).

--
Er*********@sun.com

Apr 19 '06 #2
On Wed, 19 Apr 2006 10:29:15 -0400,
Eric Sosman <Er*********@sun.com> wrote
in Msg. <1145456956.867691@news1nwk>
No. The Standard permits floating-point implementations
that support the notion of "not a number," or NaN. In IEEE
implementations, NaN is unequal to all floating-point values,
including itself (so `x == y' is false)


Makes sense. What about the non-NaN case?

robert

Apr 19 '06 #3


Robert Latest wrote On 04/19/06 11:13,:
On Wed, 19 Apr 2006 10:29:15 -0400,
Eric Sosman <Er*********@sun.com> wrote
in Msg. <1145456956.867691@news1nwk>
No. The Standard permits floating-point implementations
that support the notion of "not a number," or NaN. In IEEE
implementations, NaN is unequal to all floating-point values,
including itself (so `x == y' is false)

Makes sense. What about the non-NaN case?


The up-thread code was
double x = some_value_from_somewhere;
double y = x;

if ((x == y) && ((x - y) == 0)) {
puts("This is what I want");
}


puts() will not be called if `some_value_from_somewhere'
is a NaN, and I think it will also remain uncalled if the
value is an infinity. Even for finite values I think you are
at the mercy of the implementation. Some systems compute
intermediate values to more precision than `double' will
hold, rounding or truncating when the value is actually
stored. On such a system, the result could depend on just
what the optimizer decides to do: if `some_value_from_somewhere'
carries extra precision it is at least possible that the
generated code might do something like

compute_high_precision some_value_from_somewhere
store_rounded x
store_rounded y
compare_to y

.... thus re-using the extra-precise `some_value_from_somewhere'
instead of the normally-precise `x', and the comparison could
yield non-equal.

Floating-point implementations have a lot of quirks, even
today, and it is no wonder that the C committee decided not to
try to iron them out by fiat. Thus, the specifications of F-P
behavior in C are awfully loose, and the corner cases tend to
yield different answers on different systems. I've heard it
said (though I'm not enough of an F-P specialist to evaluate
the argument) that no high-level programming language provides
a correct implementation even of IEEE binary floating-point.

--
Er*********@sun.com

Apr 19 '06 #4
On 2006-04-19, Eric Sosman <Er*********@sun.com> wrote:
Even for finite values I think you are
at the mercy of the implementation.
[...]
Floating-point implementations have a lot of quirks, even
today, and it is no wonder that the C committee decided not to
try to iron them out by fiat.


[...]

In other words: Don't compare float values. Ever. Under no
circumstances. Be prepared that the expression

((double) 0) == (double) 0)

may evaluate to 0.

Thanks,
robert
Apr 19 '06 #5
Op 19 Apr 2006 18:39:54 GMT schreef Robert Latest:
On 2006-04-19, Eric Sosman <Er*********@sun.com> wrote:
Even for finite values I think you are
at the mercy of the implementation.


[...]
Floating-point implementations have a lot of quirks, even
today, and it is no wonder that the C committee decided not to
try to iron them out by fiat.


[...]

In other words: Don't compare float values. Ever. Under no
circumstances.

Rather a bold statement, it's only for equality.
Everyone can freely and dependently compare for less than
or greater than. ;-)
--
Coos
Apr 19 '06 #6


Robert Latest wrote On 04/19/06 14:39,:
On 2006-04-19, Eric Sosman <Er*********@sun.com> wrote:

Even for finite values I think you are
at the mercy of the implementation.

[...]

Floating-point implementations have a lot of quirks, even
today, and it is no wonder that the C committee decided not to
try to iron them out by fiat.

[...]

In other words: Don't compare float values. Ever. Under no
circumstances. Be prepared that the expression

((double) 0) == (double) 0)

may evaluate to 0.


Well, now I think you're going overboard. Equality
comparisons of F-P values are cause for raised eyebrows,
but not necessarily to be shunned in every circumstance.
For example, consider this qsort() comparator:

int compare_doubles(const void *p, const void *q) {
double u = *(const double*)p;
double v = *(const double*)q;
if (u < v) return -1;
if (u > v) return +1;
return 0;
}

There's an implicit equality comparison tucked away in
this code, and I don't think it can be eliminated: no
matter how the comparison function is written, it must
be capable of returning zero. When it returns zero, it
has, in effect, performed an equality comparison.

--
Er*********@sun.com

Apr 19 '06 #7
Coos Haak wrote:
Op 19 Apr 2006 18:39:54 GMT schreef Robert Latest:
On 2006-04-19, Eric Sosman <Er*********@sun.com> wrote:
In other words: Don't compare float values. Ever. Under no
circumstances.

Rather a bold statement, it's only for equality.
Everyone can freely and dependently compare for less than
or greater than. ;-)
--
Coos


Alas, probably not so. If I recall correctly, then according to
the strict IEEE spec, when 'x' is a NaN, the conditions (x > y),
(x == y) and (x < y) should all be FALSE. But an optimising
compiler may unsoundly choose to evaluate them differently.
--

Apr 19 '06 #8
On Wed, 19 Apr 2006 22:34:05 +0200, in comp.lang.c , Coos Haak
<ch*****@hccnet.nl> wrote:
Op 19 Apr 2006 18:39:54 GMT schreef Robert Latest:
On 2006-04-19, Eric Sosman <Er*********@sun.com> wrote:
Even for finite values I think you are
at the mercy of the implementation.


[...]
Floating-point implementations have a lot of quirks, even
today, and it is no wonder that the C committee decided not to
try to iron them out by fiat.


[...]

In other words: Don't compare float values. Ever. Under no
circumstances.

Rather a bold statement, it's only for equality.
Everyone can freely and dependently compare for less than
or greater than. ;-)


I've seen this fail too:

float s = some_value_retrieved_from_database;
if (s >4.5) puts("high interest rate!");

Mark McIntyre
--
"Debugging is twice as hard as writing the code in the first place.
Therefore, if you write the code as cleverly as possible, you are,
by definition, not smart enough to debug it."
--Brian Kernighan
Apr 19 '06 #9
In article <4a************@individual.net> Robert Latest <bo*******@yahoo.com> writes:
double x = some_value_from_somewhere;
double y = x;

if ((x == y) && ((x - y) == 0)) {
puts("This is what I want");
} .... Will the condition in the if statement always, unconditionally, and
portably evaluate to a true value?
No.
I feel a bit stupid even typing this question since I can't imagine how
x and y could possibly come out as unequal by any implementation's
standard,


Consider the situation where "some_value_from_somewhere" is calculated
in extended precision. The implementation is allowed to use that
extended precision values in every place where "x" or "y" are used,
or it may not. So it can happen that the "x" in "x == y" is retrieved
in the stored precision but that the extended precision value is used
in "y", and they possibly do not compare equal.
--
dik t. winter, cwi, kruislaan 413, 1098 sj amsterdam, nederland, +31205924131
home: bovenover 215, 1025 jn amsterdam, nederland; http://www.cwi.nl/~dik/
Apr 19 '06 #10

Eric Sosman wrote:
Well, now I think you're going overboard. Equality
comparisons of F-P values are cause for raised eyebrows,
but not necessarily to be shunned in every circumstance.
For example, consider this qsort() comparator:

int compare_doubles(const void *p, const void *q) {
double u = *(const double*)p;
double v = *(const double*)q;
if (u < v) return -1;
if (u > v) return +1;
return 0;
}

There's an implicit equality comparison tucked away in
this code, and I don't think it can be eliminated: no
matter how the comparison function is written, it must
be capable of returning zero. When it returns zero, it
has, in effect, performed an equality comparison.


#include<stdio.h>

int compare_doubles(const void *p, const void *q) {
double u = *(const double*)p;
double v = *(const double*)q;
if (u < v) return -1;
if (u > v) return +1;
return 0;
}

int main(void)
{
float u, v;
/* I'm using float here instead of double */

int value;

u = 4.50;
v = 4.50;

value = compare_doubles(&u, &v);

return value;
}

It doesnt return 0 unless i use double u,v; in main.
Whats is the wrong i'm doing by using float? Isnt that function should
itself extend float to double precision and do the things?

Apr 20 '06 #11

Naresh wrote:
Eric Sosman wrote:
Well, now I think you're going overboard. Equality
comparisons of F-P values are cause for raised eyebrows,
but not necessarily to be shunned in every circumstance.
For example, consider this qsort() comparator:

int compare_doubles(const void *p, const void *q) {
double u = *(const double*)p;
double v = *(const double*)q;
if (u < v) return -1;
if (u > v) return +1;
return 0;
}

There's an implicit equality comparison tucked away in
this code, and I don't think it can be eliminated: no
matter how the comparison function is written, it must
be capable of returning zero. When it returns zero, it
has, in effect, performed an equality comparison.


Oh sorry, I misunderstood the statement. "..and I don't think it can be
eliminated: no
matter how the comparison function is written, it must be capable of
returning zero...."

Apr 20 '06 #12
Naresh wrote:
Eric Sosman wrote:

Well, now I think you're going overboard. Equality
comparisons of F-P values are cause for raised eyebrows,
but not necessarily to be shunned in every circumstance.
For example, consider this qsort() comparator:

int compare_doubles(const void *p, const void *q) {
double u = *(const double*)p;
double v = *(const double*)q;
if (u < v) return -1;
if (u > v) return +1;
return 0;
}

There's an implicit equality comparison tucked away in
this code, and I don't think it can be eliminated: no
matter how the comparison function is written, it must
be capable of returning zero. When it returns zero, it
has, in effect, performed an equality comparison.

#include<stdio.h>

int compare_doubles(const void *p, const void *q) {
double u = *(const double*)p;
double v = *(const double*)q;
if (u < v) return -1;
if (u > v) return +1;
return 0;
}

int main(void)
{
float u, v;
/* I'm using float here instead of double */

int value;

u = 4.50;
v = 4.50;

value = compare_doubles(&u, &v);

return value;
}

It doesnt return 0 unless i use double u,v; in main.
Whats is the wrong i'm doing by using float? Isnt that function should
itself extend float to double precision and do the things?

You are pointing to floats and compare them
as doubles,of course they are not equal.
Both pointers as used add 4 random
bytes to themselfs.(assuming 4byte float and
8 byte doubles).
If there had been cleared bytes behind them,
you might even find them equal(and get bitten
later on).
Apr 20 '06 #13
Branching off of what Eric Sosman described, you could try the same
thing but with an explicit comparison of the difference with an error
constant. It would look something like this:

------------------------------
#define EPSILON 0.000001
/* ... */
if ( abs(y-x) < EPSILON )
puts("This is what I want");

----------------------------

This way, you can define how many decimal digits of equality you want
in the comparison, and in my experiance, the less-than operator is much
more stable than the equality operator, at least with floating point
numbers.

Apr 20 '06 #14
"Patrick" <fr**************@gmail.com> wrote in message
news:11**********************@i39g2000cwa.googlegr oups.com...
Branching off of what Eric Sosman described, you could try the same
thing but with an explicit comparison of the difference with an error
constant. It would look something like this:

------------------------------
#define EPSILON 0.000001
/* ... */
if ( abs(y-x) < EPSILON )
puts("This is what I want");

----------------------------

This way, you can define how many decimal digits of equality you want
in the comparison, and in my experiance, the less-than operator is much
more stable than the equality operator, at least with floating point
numbers.


Such an approach is *not* suitable for ordering floating-point values,
as in bsearch and qsort. You can end up with the situation where a == b
and b == c, but a != c. You need a strict weak ordering which is just
not all that hard to create for floating-point values. NaNs are the only
real trouble spot.

P.J. Plauger
Dinkumware, Ltd.
http://www.dinkumware.com
P.J. Plauger
Dinkumware, Ltd.
http://www.dinkumware.com
Apr 20 '06 #15

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

Similar topics

6
by: Marius Bernklev | last post by:
In python, it seems like immutable objects are equal under both equality and identity: >>> 5 == 5 True >>> 5 is 5 True >>> "hei" == "hei" True >>> "hei" is "hei"
12
by: ataru | last post by:
From the FAQ: "Non-integer results should not normally be compared for equality." Now, I understand why this ends up being true, but then what is the workaround should one actually desire to...
1
by: George Hester | last post by:
At the time this suggestion was made I didn't have the wherewithall to even attempt it. But over time I learned enough to make a stab at it. Let just say the foating DIV had to provide the same...
1
by: Doug Holland | last post by:
Currently I am responsible for writing the C# coding standards document for a client and I have been doing some investigations with ildasm to establish some additional best practices. When using...
2
by: Tristan | last post by:
Hi I'm trying to test if two Pen objects are equal as shown below Pen p1 = new Pen(Color.Black) Pen p2 = new Pen(Color.Black) if (p1.Equals(p2) Console.WriteLine("These pens equal")
2
by: Marcel Sottnik | last post by:
Hallo NG Does anyone have an idea how could one implement, a general routine for value equality ? I mean something using Reflections to get all the members of a class and compare them...
37
by: spam.noam | last post by:
Hello, Guido has decided, in python-dev, that in Py3K the id-based order comparisons will be dropped. This means that, for example, "{} < " will raise a TypeError instead of the current...
7
by: Gary Brown | last post by:
Hi, In C#, how do you determine two objects are the "same" rather than "equal?" In C/C++ you can check the addresses and LISP provides a rich set of equality operators but C# appears ambiguous....
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: ...
12
by: John Smith | last post by:
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)...
0
by: taylorcarr | last post by:
A Canon printer is a smart device known for being advanced, efficient, and reliable. It is designed for home, office, and hybrid workspace use and can also be used for a variety of purposes. However,...
0
by: aa123db | last post by:
Variable and constants Use var or let for variables and const fror constants. Var foo ='bar'; Let foo ='bar';const baz ='bar'; Functions function $name$ ($parameters$) { } ...
0
by: ryjfgjl | last post by:
If we have dozens or hundreds of excel to import into the database, if we use the excel import function provided by database editors such as navicat, it will be extremely tedious and time-consuming...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
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: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
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
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
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...

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.