5 ms·
That reasoning is incorrect. If they had chosen NaN == NaN, then the test for NaN could be simply x == NaN... The other reason mentioned is also unconvincing.
by jules 12y ago
That reasoning is incorrect. If they had chosen NaN == NaN, then the test for NaN could be simply x == NaN...
The other reason mentioned is also unconvincing. Surely preserving the law x==x is more important than the law x==y <=> x-y==0.
Then we have:
> Regarding your comment "that doesn't mean that the correct answer is false", this is wrong. The predicate (y < x) asks whether y is less than x. If y is NaN, then it is not less than any floating-point value x, so the answer is necessarily false.
Clearly this reasoning is incorrect for the simple reason that the same reasoning can lead to the opposite conclusion. If y is NaN then we can't say that y < x is definitely true but neither can we say that y < x is definitely false.
Here is my argument for why NaN == NaN should be true. The == operator for floats should rarely be used. If you want to know whether two floats can be considered the same, then you should always use some other condition like |x-y| < epsilon, and NOT x == y. The reason is that floating point arithmetic is inexact, so even a slight roundoff error will make x == y false. So if its job is not to test whether two floats are the same numerically then what is the job for the == operator? Its job is to test whether x and y are precisely the same float. The x == y operator should not pretend to work on the abstraction that x and y are kinda-sorta real numbers, because such an operator is useless anyway because the criterion for that needs to be application specific. It should compare floats while admitting that we are comparing floats which can take on the value +infinity -infinity +0 -0 and NaN, and we are not comparing real numbers which do not have those values. That's why NaN == NaN should be true.
- stephencanon 12y ago> If they had chosen NaN == NaN, then the test for NaN could be simply x == NaN Not in languages that didn’t have a name for NaN it wouldn’t. > you should always use some other condition like |x-y| < epsilon, and NOT x == y. This is a popular myth, but it is false. There are circumstances in which exact equality comparisons in floating-point are perfectly appropriate. > Its job is to test whether x and y are precisely the same float. No; if it were we would have +0 != -0. You’re looking for totalOrder(x,y) or a related predicate.
- jules 12y ago> Not in languages that didn’t have a name for NaN it wouldn’t. ...then use NaN = 0/0. > This is a popular myth, but it is false. There are circumstances in which exact equality comparisons in floating-point are perfectly appropriate. Can you give an example where == is appropriate, but where you want NaN == NaN to be false? > No; if it were we would have +0 != -0. You’re looking for totalOrder(x,y) or a related predicate. Exactly, +0 == -0 should be false too. totalOrder(x,y) is what == should have been (or at least the equality part of it). p.s. An arguably more serious issue with IEEE floats is rounding modes. The round up/round down modes are tantalizingly close to providing the ability to do ironclad approximate real arithmetic in the sense that you could give upper/lower bounds on the exact value. The problem is that the rounding modes only involve giving an upper/lower bound on the output given an exact input, rather than an upper/lower bound on the output given an upper/lower bound on the input. So it's not compositional which means you can't guarantee anything.
- thedufer 12y ago> ...then use NaN = 0/0. Many languages throw an error when you divide by zero. As far as I can tell, if x != x didn't work you would have to resort to bizarre contortions like `x == float("NaN")` for such tests in Python (the problems: there are no NaN or Infinity constants and division by 0 throws). Also, since you expect == to do bit equality on floats, you will be distinguishing between the huge number of representation of NaN, so NaN = 0/0 isn't valid even if there is a NaN constant (and which one would it be?).
- jules 12y agoStill not a valid complaint. You want to test for NaN because some computation might result in NaN. Ergo, there is some expression in your language to produce NaN. Use that expression to define NaN. Response to edit: There can be several answers to this question. If you're gonna be stuck with the IEEE floats, obviously the right thing to do is an isNaN predicate, but arguably there shouldn't be more than 1 NaN in the first place.
- derefr 12y ago
- dev360 12y agoMaybe you can explain something that puzzles me - why is (1 / 0) * (1 / (1 / 0)) equal to NaN? Edit: just checked and haskell behaves the same way.
- CHY872 12y agoInfinity * 0 returns NaN.
- mansr 12y ago> If they had chosen NaN == NaN, then the test for NaN could be simply x == NaN... There are many NaN values. Should they all compare equal to each other?