Monday, May 05, 2008

Sigh

> (eqv? +NaN.0 +NaN.0)
#t
> (eq? +NaN.0 +NaN.0)
#t
> (= +NaN.0 +NaN.0)
#f
> (equal? +NaN.0 +NaN.0)
#t

3 comments:

Anonymous said...

It's a feature not a bug. IEEE 754 mandates that NAN is not equal to any other number including NAN itself (even if it's the same bit pattern). So if X != X, you know that X is NAN.

Jason Riedy said...

Ok, this takes a bit of thinking and explaining... eqv? makes sense; two NaNs act equivalently w.r.t. typical (arithmetic) operations.

eq? is questionable and may be non-portable. The significand of a NaN may carry a payload, and some hardware systems have rules for how that payload propagates. If your Scheme implementation gives access to those features, two NaNs may be not eq?. If it doesn't, then it makes sense for a system to say two NaNs are eq?.

equal? is determined by eqv?. That may be a poor choice here, but it's standard.

And = tests numeric equality. NaN is "Not a Number", hence not a numeric quantity. Including those in numerical relations is tricky. IEEE-754 also mandates that comparisons involving non-numeric quantities signal and invalid operation condition. Few programming systems provide access to the conditions, and most that do make them nigh impossible to use.

The rationale behind returning #f for = is to allow non-stop execution; you do not want to mandate new control paths. So the operation must return some value. Returning #t leads to many errors in existing, NaN-unaware codes. Returning #f allows codes to check for NaNs even if the programming system doesn't directly support them, so long as the test is not optimized out. So the standard chose #f.

steck said...

All NaNs are equal?, but some are more = than others.

-- Paul