Previous: , Up: notes nan   [Index]


K.1.2 Understanding not–a–number

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: , Up: notes nan   [Index]