Previous: notes nan inf, Up: notes nan [Index]
NaN is a special value used as result of a wrong expression. We have seen that the composition of infinities is not always defined; in those cases the result is NaN:
(+ +inf.0 -inf.0) ⇒ +nan.0 (+ -inf.0 +inf.0) ⇒ +nan.0 (- -inf.0 -inf.0) ⇒ +nan.0 (- -inf.0 +inf.0) ⇒ +nan.0 (/ +inf.0 +inf.0) ⇒ +nan.0 (/ +inf.0 -inf.0) ⇒ +nan.0 (/ -inf.0 +inf.0) ⇒ +nan.0 (/ -inf.0 -inf.0) ⇒ +nan.0
also it is:
(div 0 0) ⇒ <error> (/ 0 0) ⇒ <error> (/ 0.0 0) ⇒ +nan.0 (/ 0 0.0) ⇒ +nan.0 (/ 0.0 0.0) ⇒ +nan.0
because, in Mathematics, 0 / 0 is not compliant to the axioms:
(0 / 0) = y ⇒ 0 * y = 0 y is not unique
Special rules were defined so that an arithmetic composition between NaN and another number always returns NaN. This allows us not to mistake a wrong computation for a correct one:
(+ 1 +nan.0) ⇒ +nan.0 (- 1 +nan.0) ⇒ +nan.0 (* 1 +nan.0) ⇒ +nan.0 (/ 1 +nan.0) ⇒ +nan.0
we have to beware, though, that some non–arithmetic function may hide the NaN, and give rise to some surprise:
(max 1 +nan.0) ⇒ 1.0 ; ! the inexact 1!! (min 1 +nan.0) ⇒ +nan.0 ; !?!
Scheme defines a predicate to test if a value is NaN, nan?
.
R6RS Scheme mandates that:
(= +nan.0 +nan.0) ⇒ #f (= +nan.0 z) ⇒ #f
for every number z. The first is correct because a wrong computation is not equal, in numerical sense, to another wrong computation.
R6RS Scheme also states that:
(eqv? +nan.0 +nan.0) ⇒ <undefined>
but currently many Scheme implementations do:
(eqv? +nan.0 +nan.0) ⇒ #t (equal? +nan.0 +nan.0) ⇒ #t
notice that, by definition, equal?
relies on eqv?
. This
allows us to do tests for wrong computations using not only nan?
;
this is especially useful when writing test suites (with more
complicated stuff than this):
(check (list (+ 1 2) (/ 0.0 0.0)) => '(3 +nan.0))
The behaviour of eqv?
and equal?
does not reduce our
ability to detect wrong expressions; we can always do:
(let ((v (expression))) (cond ((= v 1) (some-thing)) ((nan? v) (some-other-thing)) (else (yet-another-thing))))
eqv?
and equal?
just allow us to do (by definition
case
relies on eqv?
):
(case (expression) ((1 2) (some-thing)) ((+nan.0) (some-other-thing)) (else (yet-another-thing))) (let ((v (expression))) (cond ((= v 1) (some-thing)) ((eqv? v +nan.0) (some-other-thing)) (else (yet-another-thing))))
which, in some situations, is one more possibility to code the logic of a function:
(= (expression1) (expression2)) ⇒ <bool> ; true if the results are equal numbers (eqv? (expression1) (expression2)) ⇒ <bool> ; true if the results are equal numbers ; or are both wrong expressions
Previous: notes nan inf, Up: notes nan [Index]