Re:NaN does not equal NaN
by simonsarris on Tuesday September 27, 2011 @04:31PM
(#3045082)
This is of course how it is supposed to work. It is useful to define NaN this way, as a simple test for NaN is (num == num) returning false.
While we're on the topic of NaN, I'd like to mention a lesson from my little book of JavaScript you should never do[1]: You should never use null in JavaScript for the value of a yet-to-determine number. Always use NaN.
Why? It will be easier to detect problems:
var determineLater = NaN;
var blah = 5;
blah += determineLater;
blah is now NaN because (5 + NaN) is NaN. We want this because we want to know if there's been some kind of error in the making of blah
Better:
var determineLater = null;
var blah = 5;
blah += determineLater;
blah is now 5 because (5 + null) is 5. We do not want this because it doesn't let us know that there's been an error (the error typically being that determineLater was - incorrectly - never determined!)
[1] not a real book, just a text file of mis-use cases.
Re:NaN does not equal NaN
by teaspoon on Tuesday September 27, 2011 @04:51PM
(#3045178)
blah is now NaN because (5 + NaN) is NaN. We want this because we want to know if there's been some kind of error in the making of blah
Commence countdown to frontpage submission "Float is a monad". I agree with your justification for 5 + NaN evaluating to NaN, but it would be even more useful if NaN == x (and every other operation on NaN) would evaluate to NaN as well. That's obviously not possible in statically typed languages, but it is in JS.
Re:NaN does not equal NaN
by simonsarris on Tuesday September 27, 2011 @04:45PM
(#3045159)
Yes, but this is bigger than that. JavaScript doesn't define NaN, IEEE-754 defines NaN and JavaScript takes its definition from that. So it's IEEE-754 thinks num == num being false is a good test for NaN.
For the record, isNaN in JavaScript is also not necessarily the fastest way of doing it: http://jsperf.com/nantest
Re:NaN does not equal NaN
by grandpa on Tuesday September 27, 2011 @06:23PM
(#3045513)
It's things like this that make it hard to write optimizers where floating point is used. Many algebraic identities just don't apply: x == x can't be reduced to true, 0-x isn't the same as -x (it fails for +0), x<=y isn't the opposite of x>y (because of NaN), (a+b)+c isn't the same as a+(b+c), and you can't replace ac+bc with a*(b+c).
The paper "What Every Computer Scientist Should Know About Floating Point Arithmetic" is a good guide to the details.
Re:NaN does not equal NaN
by reduxredacted on Tuesday September 27, 2011 @06:05PM
(#3045454)
As a former SQL guy myself, this issue wasn't a surprise the first time I saw it.
In MSSQL (and I believe this is somewhat, though not always universal since Structured Query Language is somewhat, though rarely completely compatible between RDBMSs), NULL does not equal NULL (or anything else). In SQL terms, the idea is that it's different from "empty", it's a value with no definition---an unknown.
NaN seemed like it should work the same way. "Zed" is NaN, "Bob" is NaN, "Zed" / "Bob" is NaN. None of those are equal, they simply make no sense, so they're undefinable. (quick disclaimer: It's been a few years since I've had to actually deal with NaN in JavaScript, so if it's now possible to divide "Zed" by "Bob" in newer specs or strange implementations of JS, and not end up with NaN, feel free to correct me, I won't take it personally. I'm not writing from a position of authority on the subject).
In the land of "sort-of standard SQL", this is remedied by Field IS NULL. I can see the a similar utility in JavaScript's IsNaN. It's important to know when two things return values that the equivalent of "unknown", and not allow the unknown to equal the other unknown.
EDIT: changed "not rarely" to "rarely" in second paragraph.
Re:NaN does not equal NaN
by blahedo on Tuesday September 27, 2011 @06:54PM
(#3045609)
Even better: since SQL has a tri-valued logic (T, F, Unknown) it can assign "Unknown" as the result of a test against NULL. That means that `3 = NULL` is not true, but `3 != NULL` is also not true. If testing against NULL were merely false, then you'd have the bizarre result that
val > 3
and
not (val <= 3)
might return different results!
(I was just teaching this today in my DB class! Fun.)
Re:NaN does not equal NaN
by eftpotrm on Tuesday September 27, 2011 @04:56PM
(#3045196)
Well, yes, this is how it's supposed to work, the values being defined as unknown. SQL is the same with NULLs not matching each other.
Interestingly, this once bit me the other way round. I get so used to NaN/NULL not matching itself that it's a bit off the radar to test, yet I discovered that SAS' equivalent concept, missing, does match with itself. Which caused some head scratching to find!
Re:NaN does not equal NaN
by cdavid on Tuesday September 27, 2011 @05:05PM
(#3045225)
actually, they are both equal to infinity:
#include <stdio.h>
int main()
{
float a = 1. / 0;
float b = 2. / 0;
printf("%f == %f ? %d\n", a, b, a == b);
return 0;
}
will print:
inf == inf ? 1
Moreover:
#include <stdio.h>
int main()
{
float a = 0. / 0;
float b = a;
printf("%f == %f ? %d\n", a, b, a == b);
return 0;
}
nan == nan ? 0
So this is certainly surprising without knowing quite a bit already about floats, because it means = is not only not transitive but even not reflexive.
Re:NaN does not equal NaN
by cdavid on Tuesday September 27, 2011 @05:40PM
(#3045349)
Nobody is discussing about usual mathematical definitions: this is about the IEEE754 standard. In that context, x / 0 is defined (to positive infinity). I was pointing the error of the OP about the explanation about Nan != Nan.
Re:NaN does not equal NaN
by ajross on Tuesday September 27, 2011 @06:34PM
(#3045549)
Actually no. Just in case you were confused by cdavid's sample code: the concise explanation is that division by zero in IEEE floating point produces an infinity (there are two: positive and negative), not a NaN. Neither is necessarily an "error" in the sense of a runtime exception (the generation of which is programmable).
While we're on the topic of NaN, I'd like to mention a lesson from my little book of JavaScript you should never do[1]: You should never use null in JavaScript for the value of a yet-to-determine number. Always use NaN.
Why? It will be easier to detect problems:
blah is now NaN because (5 + NaN) is NaN. We want this because we want to know if there's been some kind of error in the making of blahBetter:
blah is now 5 because (5 + null) is 5. We do not want this because it doesn't let us know that there's been an error (the error typically being that determineLater was - incorrectly - never determined!)[1] not a real book, just a text file of mis-use cases.
Commence countdown to frontpage submission "Float is a monad". I agree with your justification for 5 + NaN evaluating to NaN, but it would be even more useful if NaN == x (and every other operation on NaN) would evaluate to NaN as well. That's obviously not possible in statically typed languages, but it is in JS.
Actually, it is more idiomatic to use undefined for this purpose rather than NaN...
For the record, isNaN in JavaScript is also not necessarily the fastest way of doing it: http://jsperf.com/nantest
Which will absolutely not matter in 100% of the cases after rounding. `isNaN` is simple (your original criteria) and clearly says what it's doing.
The paper "What Every Computer Scientist Should Know About Floating Point Arithmetic" is a good guide to the details.
You've got 2 things, but you know nothing about them. Does the fact that you know nothing about them alone make them equal?
True, they have a commonality (you know nothing about them) but that's not enough to make them equal.
All you know is what it is NOT, not what it IS. So you can't tell if it's the same as anything else.
In MSSQL (and I believe this is somewhat, though not always universal since Structured Query Language is somewhat, though rarely completely compatible between RDBMSs), NULL does not equal NULL (or anything else). In SQL terms, the idea is that it's different from "empty", it's a value with no definition---an unknown.
NaN seemed like it should work the same way. "Zed" is NaN, "Bob" is NaN, "Zed" / "Bob" is NaN. None of those are equal, they simply make no sense, so they're undefinable. (quick disclaimer: It's been a few years since I've had to actually deal with NaN in JavaScript, so if it's now possible to divide "Zed" by "Bob" in newer specs or strange implementations of JS, and not end up with NaN, feel free to correct me, I won't take it personally. I'm not writing from a position of authority on the subject).
In the land of "sort-of standard SQL", this is remedied by Field IS NULL. I can see the a similar utility in JavaScript's IsNaN. It's important to know when two things return values that the equivalent of "unknown", and not allow the unknown to equal the other unknown.
EDIT: changed "not rarely" to "rarely" in second paragraph.
Exercise: Try checking for NaN in C. Then read [1] and see if your method is cross platform like you thought
[1] http://stackoverflow.com/questions/570669/checking-if-a-doub...
This is the same as SQL where `NULL IS NULL` is true, but `NULL = NULL` is not true.
(I was just teaching this today in my DB class! Fun.)
Interestingly, this once bit me the other way round. I get so used to NaN/NULL not matching itself that it's a bit off the radar to test, yet I discovered that SAS' equivalent concept, missing, does match with itself. Which caused some head scratching to find!
What's equal to infinity is the limit of 1 / x as x approaches 0, and that's only from the positive side. From the negative side, it's -infinity.