http://people.csail.mit.edu/jaffer/III/RAWI  
Infinities in Scheme 
The three special values inf, inf, and nan of IEEE Standard 754 are welldefined and integrated into 754's arithmetic system.
With nearly every Scheme implementation using IEEE floatingpoint numbers, we should consider advancing the language to reap more of the benefits of IEEE754 by standardizing Scheme syntaxes for infinities. Doing so would also improve storage and communication of numerical data between programs.
This article contains research conducted for the SRFI70 proposal for numbers in the next revision of The Algorithmic Language Scheme. It has been updated for SCM 5e2 which implements SRFI70.
Checks for division by zero (and their absence) remain one of the most
common programming errors. Table 1,
for example, shows Scheme48 and MITScheme signaling errors evaluating
(string>number "1/0")
.
Is it merely a coincidence that these implementations are the
least tolerant (among those tested) of division by zeros?
The realization that division by zero "works" lets initialization of variables precede bounds checks and gives flexibility in placement of those checks. Halting of programs need not occur in order to test limit and corner cases. Preserving infinities in data sets can free presentation programs from imposing arbitrary range limits.
Scheme interpreter or compiler.
The Scheme program "inf.scm"
Invoke Scheme interactively, then (load "inf.scm")
;
Edit the end of "inf.scm" to call trydivs
with or
without an argument as appropriate for the Scheme's
eval
. Then compile "inf.scm" and run.
realinfs
in "inf.scm" is a list of
all known (to me) literal representations of inf,
inf, and nan.
complexinfs
in "inf.scm" is a list of the combinations
within each group of infinity representations in one or both
components of complex numbers.
The procedure str2num
prints its string argument, tries
to convert that string to a number, and writes out that number on the
same line if successful.
str2num
is called with each string in
realinfs
.
str2num
is called with each string in
complexinfs
.
The procedure trydivs
calls /
with all
possible combinations of one or two exact or inexact zeros,
printing each expression and its result.
The procedure inexprops
calls /
with
the combinations having inexact denominator "0.
" and
prints HTML rows detailing the numerical predicates applied to
the ratio.
If an error occurs while interactively running "inf.scm", the tests can be run manually:
(foreach str2num realinfs)
(foreach str2num complexinfs)
(trydivs (interactionenvironment))
(inexprops (interactionenvironment))
Input  glibc 2.2 strtod()  Gambit 4.0  Chicken 1(89)  Guile 1.8.0  Mz Scheme 301  Chez Scheme 6.1  Larceny 0.90  SCM 5e2  kawa 1.8  Scheme 48 1.3  MIT Scheme 7.8 

"+inf.0"  inf [2]  +inf.0  +inf.0  +inf.0  +inf.0  +inf.0  
"inf.0"  inf[2]  inf.0  inf.0  inf.0  inf.0  inf.0  
"+nan.0"  nan [2]  +nan.0  +nan.0  +nan.0  +nan.0  
"nan.0"  nan [2]  +nan.0  +nan.0  +nan.0  +nan.0  
"nan.0"  nan [2]  +nan.0  
"+inf."  inf [1]  +inf.  
"inf."  inf[1]  inf.  
"+nan."  nan [1]  +nan.  
"nan."  nan [1]  
"nan."  nan [1]  
"+INF"  inf  Infinity.  
"Inf"  inf  
"inf"  inf  Infinity.  
"+NAN"  nan  NaN.  
"Nan"  nan  NaN.  
"nan"  nan  NaN.  
"+#.#"  0.  5.5  
"#.#"  0.  5.5  
"#.#"  
"1/0"  Infinity.  [g]  [s]  [s]  +inf.0  1/0  [s]  
"1/0"  Infinity.  [g]  [s]  [s]  inf.0  1/0  [s]  
"0/0"  NaN.  [g]  [s]  [s]  0/0  [s]  
"#i0/0"  [n]  NaN.  [g]  +nan.0  [s]  [s]  0/0  #i0/0  [s] 
[1], [2]  Characters left at end 
[s]  ;Division by zero signaled by /. 
[n]  *** ERROR  NUMBER expected (exact>inexact #f) 
[g]  ABORT: (numericaloverflow) 
#f
was returned.
scanf()
reads identically with
strtod()
.
strtod()
also accepts "infinity", but
no substrings of it other than "inf".
string>number
does not accept "nan."
.
string>number
accepts "nan.0"
.






[g]  *** ERROR  REAL expected (makerectangular #f 1) 
#f
was returned.
string>number
accepts imaginary
infinities only with a real 0 part prepended,
eg. "0+inf.0i"
.
"#i"
lose the minus
sign.
"#i"
prefixes.
The floatingpoint string conversions in GNU glibc 2.2 support reading and writing of infinite values:
inf
is positive infinity;
inf
is negative infinity;
nan
is NotaNumber.
IEEE 754 does not specify string representations for inf and nan. These names were apparently chosen to match 754 nomenclature.
Although not specified by the Revised^{5} Report on the Algorithmic Language Scheme, a few Scheme implementations support reading and literal use of their representations of infinities.
The richness of Scheme's syntax of numerical constants provides
several opportunities to support infinities. An idea which has
occurred to several authors independently is to use #
in
place of all digits in a number:
+#.#
is positive infinity;
#.#
is negative; and
#.#
is NaN (not a number).
This notation is compact and would not be easily mistaken for any
other Scheme object. The problem arises when these objects are
components of complex numbers. The coefficient of i
must
be prefixed by a sign, making +#.#i
ambiguous.
Remediations like disallowing complex NaNs would be modifying
semantics in pursuit of syntax; not a good practice.
Gambit and MzScheme both use strings derived from IEEE754 nomenclature:
+inf.
versus +inf.0
inf.
versus inf.0
+nan.
versus +nan.0
Requiring the leading sign character prevents confusion with identifiers, but "+inf" spoofs "+i". NaN, an intrinsically unsigned construct, is required to have a sign prefix by both systems. Gambit does not recognize "nan." as NaN. MzScheme recognizes both "+nan.0" and "nan.0" as NaN, but always prints "+nan.0".
SCM 5d8 printed infinities as rational numbers with denominators of "0". SCM's existing reader decodes this format without modification:
Kawa's infinities look like inexact rational numbers.
Since an implementation is allowed to coerce the result of division by 0 to inexact, SCM always does so.
If one of these procedures is unable to deliver an exact result when given exact arguments, then it may either report a violation of an implementation restriction or it may silently coerce its result to an inexact number.
Table 3 catalogs the results of dividing exact
and inexact numbers by exact and inexact zeros. In both
MzScheme and MITScheme (/ 0 0.)
returns
"0". An inexact "0." is
apparently weaker than an exact "0" in those
implementations.
quotient  SCM 5e2  Kawa 1.8  Bigloo 2.7ar2  glibc 2.2 printf  Larceny 0.90  Guile 1.8.0  Elk 3.0  Gambit 4.0  Mz Scheme 301  Chez Scheme 6.1  MIT Scheme 7.8 

(/ 0.)  +inf.0  #i1/0  +Infinity  inf  +inf.0  +inf.0  Inf.0  +inf.  +inf.0  +inf.0  [t] 
(/ 1. 0.)  inf.0  #i1/0  Infinity  inf  inf.0  inf.0  Inf.0  inf.  inf.0  inf.0  [t] 
(/ 1 0.)  inf.0  #i1/0  Infinity  inf  inf.0  inf.0  Inf.0  inf.  inf.0  inf.0  [t] 
(/ 0. 0.)  0/0  #i0/0  Infinity  nan  +nan.0  +nan.0  NaN  +nan.  +nan.0  +nan.0  [a] 
(/ 0 0.)  0/0  #i0/0  Infinity  nan  +nan.0  +nan.0  NaN  +nan.  0  0  0 
(/ 1. 0)  inf.0  #i1/0  Infinity  inf  inf.0  [n]  [e]  [g]  [d]  [d]  [t] 
(/ 0. 0)  0/0  #i0/0  Infinity  nan  +nan.0  [n]  [e]  [g]  [d]  [d]  [a] 
(/ 0 0)  0/0  [j]  [b]  [c]  [d]  [n]  [e]  [g]  [d]  [d]  [s] 
(/ 0)  +inf.0  1/0  [b]  [c]  [d]  [n]  [e]  [g]  [d]  [d]  [s] 
(/ 1 0)  inf.0  1/0  [b]  [c]  [d]  [n]  [e]  [g]  [d]  [d]  [s] 
quotient  Scheme 48 1.3  Chicken 1(89) 

(/ any 0.)  [r]  [d] 
(/ any 0)  [r]  [d] 
[a]  ;Anonymous arithmetic error 
[b]  *** ERROR:arithmetic procedure: `floating point' exception  raised 
[c]  Floating point exception 
[d]  /: division by zero 
[e]  /: argument out of range: 0 
[g]  *** ERROR  Divide by zero 
[j]  java.lang.ArithmeticException: / by zero 
[n]  Numerical overflow 
[r]  Error: vmexception 
[s]  ;Division by zero signaled by /. 
[t]  ;Division by zero 
inexact  exact  rational  integer  real  positive  zero  negative  

Bigloo 2.7ar2  +Infinity  *  *  *  *  *  
Infinity  *  *  *  *  *  
Infinity  *  *  *  
Mz Scheme 301  +inf.0  *  *  *  *  *  
inf.0  *  *  *  *  *  
+nan.0  *  *  *  
Guile 1.8.0  +inf.0  *  *  *  *  *  
inf.0  *  *  *  *  *  
+nan.0  *  *  *  
Elk 3.0  Inf.0  *  *  *  *  *  
Inf.0  *  *  *  *  *  
NaN  *  *  
Gambit 4.0  +inf.  *  *  *  
inf.  *  *  *  
+nan.  *  *  
SCM 5e2  +inf.0  *  *  *  
inf.0  *  *  *  
0/0  *  [p]  [n]  
Kawa 1.8  #i1/0  *  *  *  
#i1/0  *  *  *  
#i0/0  *  *  
1/0  *  *  *  *  
1/0  *  *  *  * 
[p]  ;ERROR: positive?: Wrong type in arg1 0/0 
[n]  ;ERROR: negative?: Wrong type in arg1 0/0 
Table 4 shows the numerical properties of each of the special values. Only Kawa supports (2) exact infinities. For inexact infinities the only variations are in the real, rational, and integer columns.
The glibc syntax for infinities has two undesirable aspects:
Nothing visually distinguishes inf and nan from text words.
Inf and nan will be meaningless acronyms to people unfamiliar with IEEE754 who encounter them in data files.
Gambit and MzScheme address the first problem by requiring a sign
prefix. Glibc reads signed infinities, so they would
interoperate in one direction. But both implementations
add suffixes to inf and nan which
strtod()
and scanf()
do not ignore.
The SRFI70
discussions found general agreement on the +inf.0
and
inf.0
syntaxes for real infinities.
This survey of infinities in Scheme shows general agreement among implementations that scalar infinities are inexact reals. Most allow infinities as independent real and imaginary components of complex numbers.
Several implementations provide read/write invariance of inexact
complex infinities; but their syntaxes are incompatible.
Implementations should adopt the syntaxes +inf.0
and
inf.0
, which should also be incorporated into the next
Scheme standard.
I am a guest and not a member of the MIT Computer Science and Artificial Intelligence Laboratory.
My actions and comments do not reflect in any way on
MIT.  
Scheme  
agj @ alum.mit.edu  Go Figure! 