Numbers

This chapter describes Scheme’s representations for numbers.
It is important to distinguish between the mathematical numbers, the
Scheme numbers that attempt to model them, the machine representations
used to implement the Scheme numbers, and notations used to write numbers.
This report uses the types *number*, *complex*, *real*,
*rational*, and *integer* to refer to both mathematical numbers
and Scheme numbers.
The *fixnum* and *flonum* types refer to special
subtypes of the Scheme numbers, as determined by common machine
representations, as explained below.

Mathematically, numbers may be arranged into a tower of subtypes in which each level is a subset of the level above it:

number

complex

real

rational

integer

For example, 5 is an integer. Therefore 5 is also a rational,
a real, and a complex. The same is true of the Scheme numbers
that model 5. For Scheme numbers, these types are defined by the
predicates `number?`, `complex?`, `real?`, `rational?`,
and `integer?`.

There is no simple relationship between a number’s type and its representation inside a computer. Although most implementations of Scheme offer at least three different representations of 5, these different representations denote the same integer.

Scheme’s numerical operations treat numbers as abstract data, as independent of their representation as possible. Although an implementation of Scheme may use many different representations for numbers, this should not be apparent to a casual programmer writing simple programs.

It useful, however, to distinguish between numbers that are represented exactly and those that may not be. For example, indices into data structures may be required to be known exactly, as may be some polynomial coefficients in a symbolic algebra system. On the other hand, the results of measurements are inherently inexact, and irrational numbers may be approximated by rational and therefore inexact approximations. In order to catch uses of inexact numbers where exact numbers are required, Scheme explicitly distinguishes exact from inexact numbers. This distinction is orthogonal to the dimension of type.

Scheme numbers are either *exact* or
*inexact*. A number is exact if it is written as an exact
constant or was derived from exact numbers using only exact
operations. A number is inexact if it is written as an inexact
constant or was derived from inexact numbers. Thus inexactness is
contagious.

Exact arithmetic is reliable in the following sense: If exact numbers are passed to any of the arithmetic procedures described in section 9.8, and an exact number is returned, then the result is mathematically correct. This is generally not true of computations involving inexact numbers because approximate methods such as floating point arithmetic may be used, but it is the duty of each implementation to make the result as close as practical to the mathematically ideal result.

A *fixnum* is an exact integer whose value lies
within a certain implementation-dependent subrange of the
exact integers. (Library section on “Fixnums” describes a
library for computing with fixnums.)
Likewise, every implementation is required
to designate a subset of its inexact reals as *flonum*s, and
to convert certain external representations into flonums.
(Library section on “Flonums” describes a library for
computing with flonums.) Note that
this does not imply that an implementation is required to use
floating point representations.

Implementations of Scheme are required to implement the whole tower of subtypes given in section 2.1.

Implementations are required to support exact integers and exact rationals of practically unlimited size and precision, and to implement certain procedures (listed in 9.8.1) so they always return exact results when given exact arguments.

Implementations may support only a limited range of inexact numbers of any type, subject to the requirements of this section. For example, an implementation may limit the range of inexact reals (and therefore the range of inexact integers and rationals) to the dynamic range of the flonum format. Furthermore the gaps between the representable inexact integers and rationals are likely to be very large in such an implementation as the limits of this range are approached.

An implementation may use floating point and other approximate representation strategies for inexact numbers. This report recommends, but does not require, that the IEEE floating point standards be followed by implementations that use floating point representations, and that implementations using other representations should match or exceed the precision achievable using these floating point standards [25].

In particular, implementations that use floating point
representations must follow these rules: A floating point result
must be represented with at least as much precision as is
used to express any of the inexact arguments to that operation.
It is desirable (but not required) for
potentially inexact operations such as `sqrt`, when applied to exact
arguments, to produce exact answers whenever possible (for example the
square root of an exact 4 ought to be an exact 2).
If, however, an
exact number is operated upon so as to produce an inexact result
(as by `sqrt`), and if the result is represented in floating
point, then the most precise floating point format available
must be used; but if the result
is represented in some other way then the representation must have
at least as much precision as the most precise
floating point format available.

It is the programmer’s responsibility to avoid using inexact numbers with magnitude or significand too large to be represented in the implementation.

Positive infinity is regarded as a real (but not rational) number, whose value is indeterminate but greater than all rational numbers. Negative infinity is regarded as a real (but not rational) number, whose value is indeterminate but less than all rational numbers.

A NaN is regarded as a real (but not rational) number whose value is so indeterminate that it might represent any real number, including positive or negative infinity, and might even be greater than positive infinity or less than negative infinity.

Some Scheme implementations, specifically those that follow the IEEE
floating point standards, distinguish between 0.0 and `-` 0.0, i.e.,
positive and negative inexact zero. This report will sometimes
specify the behavior of certain arithmetic operations on these
numbers. These specifications are marked with “if `-` 0.0 is
distinguished” or “implementations that distinguish `-` 0.0”.