The three ways to compare floatingpoint numbers
One bit of advice sometimes given to the novice programmer is don't ever compare floatingpoint numbers for equality, the reason being that floatingpoint calculations are inexact, and one should use a small epsilon, allowable error, instead, e.g. if (abs(value  1.0) < 0.0001)
.
This advice is actually wrong, or rather, overly strong. There is a situation in which it is 100% valid to compare floats, and that is an cache or anything else which is comparing a float with, not a specific constant (in which case the epsilon notion is appropriate), but rather a previous value from the same source; floatingpoint numbers may be approximations of exact arithmetic, but that doesn't mean you won't get the same result from the same inputs.
So, don't get any bright ideas about outlawing aFloat == anotherFloat
.
Unfortunately, there's a case in which the common equality on floats isn't what you want for previousvalue comparison anyway: for most definitions of ==
, NaN ≠≠ NaN
. This definition makes sense for numerics (and is conformant to IEEE floating point specifications), because NaN
is “not a number”; it's an error marker, provided as an alternative to exceptions (or rather, floating point error signals/traps/whateveryoucallit) which propagates to the end of your calculation rather than aborting it and requiring immediate error handling, which can be advantageous in both code simplicity and efficiency. So if you think about calculating within the space of “numbers”, then NaN is outside of that. But if you're working in the space of “results of calculations”, then you probably want to see NaN == NaN
, but that may not be what you get.
Mathematically, the floatingpoint comparison is not an equivalence relation, because it is not reflexive on NaN
.
(It's also typically the case that 0 == 0
, even though positive and negative zero are distinct values. Oh, and NaNs carry data, but I'm not talking about that.)
What to do about it, in a few languages:
 JavaScript
Even the
===
operator does not compare identities rather than numeric values, so if you want to compareNaN
you have to do it as a special case. Google Caja handles it this way:/** * Are x and y not observably distinguishable? */ function identical(x, y) { if (x === y) { // 0 === 0, but they are not identical return x !== 0  1/x === 1/y; } else { // NaN !== NaN, but they are identical. // NaNs are the only nonreflexive value, i.e., if x !== x, // then x is a NaN. return x !== x && y !== y; } }
 Common Lisp
The
=
operator generally follows the IEEE comparison (if the implementation has NaN at all) and theeql
operator does the identicalobject comparison. E

The
==
operator is guaranteed to be reflexive, and return false for distinguishable objects, so it is appropriate for the “cachelike” use cases, and the<=>
operator does conventional!(NaN <=> NaN), 0.0 <=> 0.0
floatingpoint comparison.
Mathematically floating point isn't much of anything
NaN and inf really bugger up the properties of floating point, as well as negative zero.
Re: Mathematically floating point isn't much of anything
Re: Mathematically floating point isn't much of anything
Not much is closed with floating point. It is annoying how static typing won't help you here unless you define a wrapper type which outright bans NaNs and Infs. You might get along with just banning NaN.
*sigh*
(NaN == NaN) is "MayBe"
http://en.wikipedia.org/wiki/Trivalent_l
Makes any sense to you?
Re: (NaN == NaN) is "MayBe"
Floatingpoint numbers don't magically turn fuzzy as soon as they are instantiated; rounding error results from computation and is not innate to a number being a floatingpoint number.
True ... mostly! The one catch is that many processors will internally compute floatingpoint numbers to a higher accuracy than required (like 80 bits rather than 64). So depending on your code and compiler, an immediate floatingpoint number (in the FPU) might not compare equal to itself if one side of the test has been stored in a 64bit storage location.
'because NaN is “not a number”; it's an error marker'
http://bertrandmeyer.com/2010/02/06/refl