double.NaN - Bug? Whats the story behind?

G

Guest

A little preamble
A year ago I had a very odd bug in my program, in an if clause it picked and executed the else statement even though the if clause should evaluate to true. Normally you know that it is you who are doing something wrong, but not this time. Contacting microsoft and providing them with the code, they informed me that there was a bug in VS, and that an upgrade to VS 2003 would solve the problem - they were right and thus the problem were solved. However my confidence in VS .Net had suffered.

Today - I look at a problem that is much like the above described. In the following code, the Property Pitch returns double.NaN - when debugging, the left and right side in the if clause below match, however, the else statement is executed
MY QUESTION - is this a new bug in VS .Net or should I be able write code as below

if (layer.Pitch == double.NaN

this.labelPitch.Text = "--"

else.....
 
F

Frank Oquendo

Jesper said:
MY QUESTION - is this a new bug in VS .Net or should I be able write
code as below?

Neither. Use double.IsNaN instead.

--
There are 10 kinds of people. Those who understand binary and those who
don't.

http://code.acadx.com
(Pull the pin to reply)
 
B

Bruno Jouhier [MVP]

This is mandated by IEEE 754 specs:

Arithmetic operations between NaN and anything else (a number, infinity, or
NaN) always result in NaN. Equality omparison between two NaN numbers is
always false.

Actually, Java behaves the same, and the source for Double.isNaN in Java is:

static public boolean isNaN(double v) { return (v != v); } // compiler has
to be smart and not optimize it!!!

To me, this sounds like a strange design decision (I agree on the first
part, arithmetic operations producing NaN but not on the comparison rule),
but this is how the IEEE guys see the world and we have to live with it. You
have to test with Double.IsNaN(d) rather than with d == double.NaN

Bruno.

Jesper said:
A little preamble.
A year ago I had a very odd bug in my program, in an if clause it picked
and executed the else statement even though the if clause should evaluate to
true. Normally you know that it is you who are doing something wrong, but
not this time. Contacting microsoft and providing them with the code, they
informed me that there was a bug in VS, and that an upgrade to VS 2003 would
solve the problem - they were right and thus the problem were solved.
However my confidence in VS .Net had suffered.
Today - I look at a problem that is much like the above described. In the
following code, the Property Pitch returns double.NaN - when debugging, the
left and right side in the if clause below match, however, the else
statement is executed.
 
J

Jon Skeet [C# MVP]

Bruno Jouhier said:
This is mandated by IEEE 754 specs:

Arithmetic operations between NaN and anything else (a number, infinity, or
NaN) always result in NaN. Equality omparison between two NaN numbers is
always false.

Actually, Java behaves the same, and the source for Double.isNaN in Java is:

static public boolean isNaN(double v) { return (v != v); } // compiler has
to be smart and not optimize it!!!

To me, this sounds like a strange design decision (I agree on the first
part, arithmetic operations producing NaN but not on the comparison rule),
but this is how the IEEE guys see the world and we have to live with it. You
have to test with Double.IsNaN(d) rather than with d == double.NaN

I believe the point on the comparison rule is that the NaNs could have
come from very different "non-real-number" results. For instance,
sqrt(-9) != sqrt(-1) but both may well come out to the same NaN. On the
other hand, sqrt(-1) == sqrt(-1) but that won't be acknowledged :(
 
B

Bruno Jouhier [MVP]

To me, this sounds like a strange design decision (I agree on the first
I believe the point on the comparison rule is that the NaNs could have
come from very different "non-real-number" results. For instance,
sqrt(-9) != sqrt(-1) but both may well come out to the same NaN. On the
other hand, sqrt(-1) == sqrt(-1) but that won't be acknowledged :(

Yes, the sqrt(-9) != sqrt(-1) case makes sense, but the fact that you cannot
use d == double.NaN to test if a number is NaN is very disturbing.

Even worse:
object nan1 = (object)double.NaN
object nan2 = (object)double.NaN
nan1.Equals(nan2) is .... True!
double.NaN == double.NaN is ... False (of course)!

Same in Java:
new Double(double.NaN).equals(new Double(double.NaN)) is ... true!
double.NaN == double.NaN is ... false!

So, Equals is overriden to give "value" semantics, but the value semantics
that you get does not match the semantics of the double type. These design
choices are completely arbitrary and inconsistent. I cannot make any sense
out of them :(

Bruno.
 
J

Jon Skeet [C# MVP]

Bruno Jouhier said:
Yes, the sqrt(-9) != sqrt(-1) case makes sense, but the fact that you cannot
use d == double.NaN to test if a number is NaN is very disturbing.

I believe the reason for that is that there are several types of NaN
(different bit patterns).
Even worse:
object nan1 = (object)double.NaN
object nan2 = (object)double.NaN
nan1.Equals(nan2) is .... True!
double.NaN == double.NaN is ... False (of course)!

Same in Java:
new Double(double.NaN).equals(new Double(double.NaN)) is ... true!
double.NaN == double.NaN is ... false!

So, Equals is overriden to give "value" semantics, but the value semantics
that you get does not match the semantics of the double type. These design
choices are completely arbitrary and inconsistent. I cannot make any sense
out of them :(

According to the Java 1.4.1 docs, the reason for this exception (and
that +0.0.Equals(-0.0) gives false) is to get Hashtables to work
correctly - I can see why that should be.

It's basically one of those fundamentally horrible bits of computer
science, like dates/times and character sets. (Character sets and
encodings aren't too bad in the simple case, but when you start having
to worry about combining characters and surrogates, it gets nasty in a
hurry.)
 
B

Bruno Jouhier [MVP]

According to the Java 1.4.1 docs, the reason for this exception (and
that +0.0.Equals(-0.0) gives false) is to get Hashtables to work
correctly - I can see why that should be.

Makes sense too (in the middle of all the nonsense).
It's basically one of those fundamentally horrible bits of computer
science, like dates/times and character sets. (Character sets and
encodings aren't too bad in the simple case, but when you start having
to worry about combining characters and surrogates, it gets nasty in a
hurry.)

Agreed. And we have to live with standards that don't always make our life
simpler.

Unicode is a good example: it solves a big problem by covering all the
writing systems in a uniform way but it could have been much better. This
idea of having 2 ways to represent the same character (composed and
precomposed) is just a very bad idea because even the most basic basic
string comparison requires some difficult coding. Also, the idea of putting
the diacritical mark in postfix rather than prefix position is the sign that
the people who designed this standards have never programmed anything (makes
substring comparison even more difficult because you have to look-ahead!)

Bruno.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top