NaN does not equal NaN
swizec.com
swizec.com
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 blahBetter:
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.
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.
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...
var determineLater; // undefined
var blah = 5;
blah += determineLater; // blah is now NaNThe 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...
sqlite> SELECT 1=1;
1
sqlite> SELECT 1=0;
0
sqlite> SELECT NULL!=NULL;
sqlite> SELECT NULL=NULL;This is the same as SQL where `NULL IS NULL` is true, but `NULL = NULL` is not true.
val > 3
and not (val <= 3)
might return different results!(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!
#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.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.