Imagine doing if(x) ..., where x can be NaN. Shouldn't that throw an exception in most cases? Why are our compilers not doing it that way?
Demystifying NaN for the Working Programmer
11–20 of 38 posts
Re: Demystifying NaN for the Working Programmer
#12Earlier quoted context omitted.
Signaling NaNs raise exceptions in some operations. Is comparison one of these?
They “raise exceptions” in the IEEE 754 sense, which is not at all the same thing as what most programming languages mean by “raise exception”. It means that they set a sticky flag in a register that may be queried at a later point, not that program control flow is redirected.
Re: Demystifying NaN for the Working Programmer
#13I did a code assignment for a potential JavaScript heavy job in 2014, for some reason I think isNaN was part of the language then because I have a memory deciding not to use it (but could be misremembering), at any rate I did Number(x) !== Number(x) at some point. In the meeting when they went over the code the guy who did it said we were wondering why you did this? So I had to explain NaN to him. He really did not k…
Re: Demystifying NaN for the Working Programmer
#14Imagine doing if(x) ..., where x can be NaN. Shouldn't that throw an exception in most cases? Why are our compilers not doing it that way?
Should it? It isn't obvious to me at all that throwing an exception in this case is the best behaviour. Throwing an exception when testing a value for 'truthiness' is extremely surprising. On the other hand, I would strongly discourage 'if(x)' where x is a float that may be NaN purely because the 'correct' behaviour here isn't clear to me.
Re: Demystifying NaN for the Working Programmer
#15Earlier quoted context omitted.
They “raise exceptions” in the IEEE 754 sense, which is not at all the same thing as what most programming languages mean by “raise exception”. It means that they set a sticky flag in a register that may be queried at a later point, not that program control flow is redirected.
The only use I saw for this is that you can enable compiler flags to crash the program when NaNs are encountered. Useful for testing Fortran code, in my experience. I didn’t see any support for other languages I’ve used.
Re: Demystifying NaN for the Working Programmer
#16Pointers 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.
Re: Demystifying NaN for the Working Programmer
#17Earlier quoted context omitted.
Should it? It isn't obvious to me at all that throwing an exception in this case is the best behaviour. Throwing an exception when testing a value for 'truthiness' is extremely surprising. On the other hand, I would strongly discourage 'if(x)' where x is a float that may be NaN purely because the 'correct' behaviour here isn't clear to me.
How about the case where x is (y > 0)? If y is NaN, shouldn't x be boolean-NaN? And shouldn't if(x) throw an exception? Or shouldn't (y > 0) throw an exception if you don't want boolean-NaNs?
You may not think this is wise, but this is very much how comparisons with NaN are defined.
And I think this is better than exception raising. Again, I think it would be _really_ weird for simple value comparisons to throw.
Re: Demystifying NaN for the Working Programmer
#18NaN 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 invali…
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?
Re: Demystifying NaN for the Working Programmer
#19Zero/zero doesn’t return NaN because it isn’t representable within floating point - it returns NaN because it is an expression that has no mathematical meaning.
The fact that sqrt(-1) has two valid nonreal answers has nothing to do with why it returns NaN - after all, sqrt(4) has two valid real answers so is also technically not representable by a single floating point value, but that doesn’t typically result in NaN.
NaN is just an error value you get when you ask floating point math a dumb question it can’t usefully answer.
Far more interesting and subtle are the ways in which positive and negative infinity and positive and negative zero let you actually still obtain useful (at least for purposes of things like comparison) results to certain calculations even if they overflow the representable range.
Re: Demystifying NaN for the Working Programmer
#20Earlier quoted context omitted.
How about the case where x is (y > 0)? If y is NaN, shouldn't x be boolean-NaN? And shouldn't if(x) throw an exception? Or shouldn't (y > 0) throw an exception if you don't want boolean-NaNs?
That's easy: y > 0 is False, not NaN. You may not think this is wise, but this is very much how comparisons with NaN are defined. And I think this is better than exception raising. Again, I think it would be _really_ weird for simple value comparisons to throw.
But ... why?
You may say that NaN > 0 is defined as False, but we know that's not how programmers think, most of the time.
In code like if(y > 0) steer_car_to_left() I don't want the compiler or the IEEE standard to make any choices for me! Let it throw, so emergency systems can kick in.