Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

NaN is a cancer. The choice that NaN == Nan being false is just wrong. Every type, every variable can have multiple reason for being invalid. Yet, no other type has ever chosen to make invalid values not being equal to themselves.

Pointers can be invalid. They can be invalid for any number of reason. Lack of memory, object not found, etc. No one ever suggest that null should not equal null.

File handle can be invalid. They can be invalid for any number of reasons: file not found, access denied, file server is offline. No one has ever made invalid handles not being equal to themselves.

The justification for NaN not being equal to themselves is just bonk.




In a world without generic programming, NaN not being equal to itself makes a certain amount of sense for some kinds of numeric code. But in a world with reusable generic algorithms the calculation changes -- here equality/ordering relations really must be transitive or weird shit happens. In C++ it's undefined behavior to call `std::sort` or `std::unique` on list of floats containing NaN.

Most languages nowadays have standard-library functions/types that require well-behaved equality, so why have a builtin type for which equality is not well-behaved?


>The justification for NaN not being equal to themselves is just bonk.

It makes a lot of sense to me. NaN indicates data has been lost. You did something and you stored the result in a number datatype but the result isn't a number. Data was lost. You lost the data and have only 'your answer wasn't a number.'

Comparing NaN with NaN is asking the computer 'we have two buckets that have overflowed, were their contents the same?' The answer is 'we don't know' which means, to err on the side of safety, the answer is 'no.'

No?


Let's say you make a particular NaN equal to itself.

But then it's sensible for different operations to give you different NaN values.

And you still wouldn't say that 4 < NaN is true, or NaN < 4 is true, would you?

So it's still going to confuse the user. Is just changing equality going to give you a better system overall?


Infinity is NaN, but 4 < infinity is true.


Signed infinity represents aggressive rounding, but you still know roughly what number it is. It works out well to let it still participate in equality and ordering. NaN can be created in many different ways and there is no way to say basically anything about what numbers it could be related to.

You could arbitrarily make NaN sort as if it was a certain value, and that would be useful when you want to sort a big array, but it would have unpleasant side effects when you're doing math. IEEE decided "always false" was less likely to cause problems, but to be clear you get problems no matter what you choose.


My point was you can have multiple types of “Not a Number” used at the same time.

Defining just error, undefined, positive infinity, and negative infinity is far from an exhaustive list but they obviously should be treated differently in many contexts.


Well let's look at wikipedia's list of things that cause IEEE NaN, since they already split out Infinity.

0/0, ∞/∞, ∞%n, n%0, ∞-∞, results with imaginary components

The first five have no meaningful approximation or way to interact with anything. And there's no good way to pretend a single float is a complex number.

So those results get the "this doesn't exist" treatment. Coder's choice if NaN triggers errors or not.

Would you try to define any more behavior for any of those NaNs?


Only if you wanted to treat them as more severe types of NaN, Aka ∞-∞ - ∞ can evaluate to ∞-∞, but ∞-∞ / 0 = 0/0.

Though really that choice is just about what kind of errors you’re showing users.


infinity is not NaN


IEEE 754 NaN’s are arguably defined as different things, but that’s not the only system to use floating point Math and NaN.

Mathematically different infinities are not equivalent because infinity is not a number. How you represent that is dependent on the specific system involved.


Since math is one of the few things I fell confident talking about:

It is true that different infinities exists[0][1] and there are whole areas of logic examining them.

It is also true that _number_ without any extra qualifier generally means the Real numbers (R) or Complex numbers (C) and those domain do not define infinity as a number, but even then there are only a few good ways to add infinity into each number system:

In R generally you either add a projective point of infinity ∞ [2] that makes geometry sometimes nices or two signed infinities (-∞ and +∞) that make calculus nicer (especially limits and integration)

In C it is often simpler as typically you want to treat them as a sphere and so add an extra point so that the inversion f(x) = 1/x is a well-behaved function. In this domain you often end up working with holomorphic functions[3] and then there is not really an intrinsic difference between a function like f(x) = 1/x and g(x) = x they simply have both a _pole_ f at 0 and g at infinity.

If you want to get trippy even integers can have unusual definitions [4] and then there is always one of my favorite topic in math: surreal numbers [5] (for which I recommend both [6] and [7]) a field where √∞ < ∞/2 < ∞ - 1 < ∞ < ∞ + 1 and is perfectly well defined (but still 0/0 doesn't have any meaning in any of these theories, that is a though nut to crack)

[0]https://en.wikipedia.org/wiki/Ordinal_number [1]https://en.wikipedia.org/wiki/Cardinal_number [2]https://en.wikipedia.org/wiki/Projective_geometry [3]https://en.wikipedia.org/wiki/Holomorphic_function [4]https://en.wikipedia.org/wiki/Algebraic_integer [5]https://en.wikipedia.org/wiki/Surreal_number [6]https://www-cs-faculty.stanford.edu/~knuth/sn.html [7]https://books.google.it/books?id=tXiVo8qA5PQC&redir_esc=y


Note (without disagreeing). In SQL NULL!= NULL




Consider applying for YC's Fall 2025 batch! Applications are open till Aug 4

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: