6 ms·
> That’s also the reason NaN !== NaN. If NaN behaved like a number and had a value equal to itself, well, you could accidentally do math with it: NaN / NaN woul
by KalMann 1y ago
> That’s also the reason NaN !== NaN. If NaN behaved like a number and had a value equal to itself, well, you could accidentally do math with it: NaN / NaN would result in 1, and that would mean that a calculation containing a NaN result could ultimately result in an incorrect number rather than an easily-spotted “hey, something went wrong in here” NaN flag.
While I'm not really against the concept of NaN not equaling itself, this reasoning makes no sense. Even if the standard was "NaN == NaN evaluates to true" there would be no reason why NaN/Nan should necessarily evaluate to 1.
- ema 1y agoMaybe the result of NaN === NaN should be neither true nor false but NaB (not a bool).
- disgruntledphd2 1y agoIn R, NA (which is almost, but not quite like NaN) actually has separate types for each result, so you can have NA_boolean, NA_integer etc. Its super confusing.
- getnormality 1y agoIt is a minor nuisance, but I think there's ultimately a pretty good reason for it. Old-school base R is less type-sensitive and more "do what I mean", but that leads to slowness and bugs. Now we have the tidyverse, which among many other things provides a new generation of much faster functions with vectorized C implementations under the hood, but this requires them to be more rigid and type-sensitive. When I want to stick a NA into one of these, I often have to give it the right type of NA, or it'll default to NA_boolean and I'll get type errors.
- disgruntledphd2 1y ago> When I want to stick a NA into one of these, I often have to give it the right type of NA, or it'll default to NA_boolean and I'll get type errors. Yeah, I know. I hit this when I was building S4 classes, which are similarly type-strict. Again, I think this was the right decision (pandas's decision was definitely not), but it was pretty confusing the first time.
- monkpit 1y agoNaN is, by definition, not equal to NaN because they’re not comparable, it does have a definitive Boolean representation - false is correct
- deleted 1y ago[deleted]
- zahlman 1y agoThe concept of NaN long predates the language that uses ===, and is part of a language-agnostic standard that doesn't consider other data types. Any language choosing to treat the equality (regardless of the operator symbol) of NaN differently would be deviating from the spec.
- freehorse 1y agoJulia evaluates NaN === NaN to true, as long as the underlying bit representations are the same. Eg NaN === -NaN evaluates to false, as happens also with NaNs where for some reason you tinker with their bytes. I think it makes sense that it is so though, regardless that I cannot think of any actual use cases out of doing weird stuff.
- steveBK123 1y agoTyped nulls are good
- charcircuit 1y agoOr a 3rd option is it should not be allowed similar to dividing by 0.
- freehorse 1y agoWhat do you mean "not allowed"? Throwing a compile or runtime error? Many languages allow division by zero, and x/0 typically gives inf unless x is 0, then x/0 gives nan. If x is negative then x/0 gives -inf. Of course this all can get tricky with floats, but mathematically it makes sense to divide by zero (interpreted as a limit). For NaNs, maybe in some domains it could make sense, but eg I would find it impractical when wanting to select rows based on values in a column and stuff like that.
- sophrosyne42 1y agoIt should throw a compile-time error. Anything like this which allows an invalid or unmeaningful operation to evaluate at compile-time is rife for carrying uncaught errors at run-time.
- freehorse 1y agoWhat would an `if (NaB) ... else ...` block do? Either you throw an exception (and imo it is better to just throw an exception before that already, then) or else what you do determines what NaN === NaN actually evaluates to.
- lioeters 1y agoApparently NaN (not a number) becomes false when type-cast to boolean. Boolean(NaN) ===> false For a hypothetical NaB (not a boolean), the same behavior seems logical. Boolean(NaB) ===> false So the condition `if (NaB)` is false and will fall through to the `else` branch. But.. > what you do determines what NaN === NaN actually evaluates to I think I disagree with this because it's not about casting to boolean, it's a totally different question of self-identity, or comparing two instances (?) of a value (?!). From the article: typeof NaN ===> "number" For symmetry and consistency: typeof NaB ===> "boolean" > NaN is the only value in the whole of JavaScript that isn’t equal to itself .. the concept of NaN is meant to represent a breakdown of calculation Similarly, NaB would represent a breakdown of true/false condition (somehow) as an exceptional case. Whether it equals itself is a matter of convention or language design, not logic - since it's beyond logic just as NaN is beyond numbers. I would say: NaN === NaN ===> false NaB === NaB ===> false > you throw an exception (and imo it is better.. I agree throwing an exception is better design for such exceptional cases - but we know JavaScript as a cowboy language would rather plow through such ambiguities with idiosyncratic dynamic typing, and let the user figure out the implicit logic (if any).
- freehorse 1y agoI don't necessarily think about JS in particular. A lot of languages have similar design and prob most have to deal with this issue in general. In your examples, it does not make sense to have both typeof NaB ===> "boolean" and Boolean(NaB) ===> false But maybe if you had NaB it would make sense to evaluate Boolean(NaN) ===> NaB And maybe also evaluate `NaN === 1` to NaB? I am not too fond of NaB because boolean is supposed to encode binary logic. There exists ternary logic and other concepts that could be used if you do not want strictly two values. Or if you want to encode exceptional values, no reason not to use int8 directly, instead of calling it boolean but actually using sth that could be represented as int8 (NaB has to be represented by some byte anwyay). In general, tbh, I think often it is not useful to encode your logic with booleans because many times you will need to encode exceptional values one way or another. But NaB will not solve that, as it will just function as another way to encode false at best, throwing exceptions around at worst. > Similarly, NaB would represent a breakdown of true/false condition (somehow) as an exceptional case. Still, in JS `NaN || true` evaluates to `true` hence I assume `NaB || true` should evaluate to true too. It is not quite the same as NaN + 1 evaluating to NaN. And as NaN (and hence NaB) functions as false when logical operations are involved for all intents and purposes, except if you exactly inquire for it with some isNaB() or sth, to me NaB is another way to encode false, which is probably fine depending what you want it for.
- JohnMakin 1y agoBecause NaN is defined as a number and two equal numbers divided by themselves equal 1
- mbrubeck 1y ago> two equal numbers divided by themselves equal 1 That's not true. For example: 0 == 0, but 0/0 != 1. (See also +Infinity, -Infinity, and -0.)
- JohnMakin 1y agoIf you're going to nitpick this comment, you should note that infinity isn't on the number line and infinity != infinity, and dividing by zero is undefined
- mbrubeck 1y agoWe're commenting on an article about IEEE 754 floating point values. Following the IEEE 754 standard, we have: >> isNaN(Infinity) false >> Infinity == Infinity true >> Infinity / Infinity == 1 false >> isNaN(0) false >> 0 == 0 true >> 0 / 0 == 1 false Also, you say NaN ("not a number") is "defined as a number" but Infinity is not. I would think every IEEE 754 value is either "a number" or "not a number". But apparently you believe NaN is both and Infinity is neither? And you say 0 / 0 is "undefined" but the standard requires it to be NaN, which you say is "defined".
- KalMann 1y agoIt doesn't really matter if NaN is technically a number or not. I find the standard "NaN == NaN is true" to be potentially reasonable (though I do prefer the standard "NaN == Nan is false"). Regardless of what you choose NaN/NaN = 1 is entirely unacceptable.
- nikeee 1y agoI think a better reasoning is that NaN does not have a single binary representation but in software, one may not be able to distinguish them. An f32-NaN has 22 bits that can have any value, originally intended to encode error information or other user data. Also, there are two kinds of NaNs: queit NaN (qNaN) and signalling NaNs (sNaN) which behave differently when used in calculations (sNaNs may throw exceptions). Without looking at the bits, all you can see is NaN, so it makes sense to not equal them in general. Otherwise, some NaN === NaN and some NaN !== NaN, which would be even more confusing.
- munificent 1y agoI don't think that logic quite holds up because when you have two NaNs that do have the same bit representation, a conforming implementation still has to report them as not equal. So an implementation of `==` that handles NaN still ends up poking around in the bits and doing some extra logic. It's not just "are the bit patterns the same?" (I believe this is also true for non-NaN floating point values. I'm not sure but off the top of my head, I think `==` needs to ignore the difference between positive and negative zero.)
- freehorse 1y ago> NaN === NaN and some NaN !== NaN In julia NaN === NaN evaluates to true but NaN === -NaN evaluates to false. Of course, NaN == NaN evaluates to false. I think it makes sense that in principle === looks at bit representations, but cannot think of any reason === is useful here, unless you want to encode meaningful stuff inside your NaNs for some reason. It reminded me of this satirical repo [0] discussed also here [1]. [0] https://github.com/si14/stuffed-naan-js https://github.com/si14/stuffed-naan-js [1] https://news.ycombinator.com/item?id=43803724 https://news.ycombinator.com/item?id=43803724
- naet 1y agoI definitely support NaN not being equal to NaN in boolean logic. If you have x = "not a number", you don't want 1 + x == 2 + x to be true. There would be a lot of potential for false equivalencies if you said NaN == NaN is true. -- It could be interesting if there was some kind of complex NaN number / NaN math. Like if x is NaN but 1x / 2x resulted in 0.5 maybe you could do some funny mixed type math. To be clear I don't think it would be good, but interesting to play with maybe.
- grogers 1y agoDoesn't "1 + x == 2 + x" evaluate to true for any x with large enough magnitude? In general we should expect identities that hold true in "real" math to not hold in FP
- bogdanoff_2 1y agoSomething like: // Optimize special case if (x == y) return 1; else return x/y;