Velocity Reviews > Equality of floating-point numbers (special case)

# Equality of floating-point numbers (special case)

Robert Latest
Guest
Posts: n/a

 04-19-2006
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

Eric Sosman
Guest
Posts: n/a

 04-19-2006

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).

--
http://www.velocityreviews.com/forums/(E-Mail Removed)

Robert Latest
Guest
Posts: n/a

 04-19-2006
On Wed, 19 Apr 2006 10:29:15 -0400,
Eric Sosman <(E-Mail Removed)> 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

Eric Sosman
Guest
Posts: n/a

 04-19-2006

Robert Latest wrote On 04/19/06 11:13,:
> On Wed, 19 Apr 2006 10:29:15 -0400,
> Eric Sosman <(E-Mail Removed)> 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?

>>> 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.

--
(E-Mail Removed)

Robert Latest
Guest
Posts: n/a

 04-19-2006
On 2006-04-19, Eric Sosman <(E-Mail Removed)> 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

Coos Haak
Guest
Posts: n/a

 04-19-2006
Op 19 Apr 2006 18:39:54 GMT schreef Robert Latest:

> On 2006-04-19, Eric Sosman <(E-Mail Removed)> 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

Eric Sosman
Guest
Posts: n/a

 04-19-2006

Robert Latest wrote On 04/19/06 14:39,:
> On 2006-04-19, Eric Sosman <(E-Mail Removed)> 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.

--
(E-Mail Removed)

bert
Guest
Posts: n/a

 04-19-2006
Coos Haak wrote:
> Op 19 Apr 2006 18:39:54 GMT schreef Robert Latest:
> > On 2006-04-19, Eric Sosman <(E-Mail Removed)> 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.
--

Mark McIntyre
Guest
Posts: n/a

 04-19-2006
On Wed, 19 Apr 2006 22:34:05 +0200, in comp.lang.c , Coos Haak
<(E-Mail Removed)> wrote:

>Op 19 Apr 2006 18:39:54 GMT schreef Robert Latest:
>
>> On 2006-04-19, Eric Sosman <(E-Mail Removed)> 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

Dik T. Winter
Guest
Posts: n/a

 04-19-2006
In article <(E-Mail Removed)> Robert Latest <(E-Mail Removed)> 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/