This chapter describes Scheme’s model for numbers. It is important to distinguish between the mathematical numbers, the Scheme objects that attempt to model them, the machine representations used to implement the numbers, and notations used to write numbers. In this report, the term number refers to a mathematical number, and the term number object refers to a Scheme object representing a number. This report uses the types complex, real, rational, and integer to refer to both mathematical numbers and number objects. The fixnum and flonum types refer to special subsets of the number objects, as determined by common machine representations, as explained below.
Numbers may be arranged into a tower of subsets 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 number objects that model 5.
Number objects are organized as a corresponding tower of subtypes defined by the predicates number?, complex?, real?, rational?, and integer?; see section 9.8.4.1. Integer number objects are also called integer objects.
There is no simple relationship between the subset that contains a number and its representation inside a computer. For example, the integer 5 may have several representations. Scheme’s numerical operations treat number objects 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 to distinguish between number objects that are known to correspond to a number exactly, and those number objects whose computation involved rounding or other errors. 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 numbers known only inexactly where exact numbers are required, Scheme explicitly distinguishes exact from inexact number objects. This distinction is orthogonal to the dimension of type.
Numbers objects are either exact or inexact. A number object is exact if it is the value of an exact numerical literal or was derived from exact number objects using only exact operations. Exact number objects correspond to mathematical numbers in the obvious way.
Conversely, a number object is inexact if it is the value of an inexact numerical literal, or was derived from inexact number objects, or was derived using inexact operations. Thus inexactness is contagious.
Exact arithmetic is reliable in the following sense: If exact number objects are passed to any of the arithmetic procedures described in section 9.8.1, and an exact number object is returned, then the result is mathematically correct. This is generally not true of computations involving inexact number objects 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 object that lies within a certain implementation-dependent subrange of the exact integer objects. (Library section on “Fixnums” describes a library for computing with fixnums.) Likewise, every implementation is required to designate a subset of its inexact real number objects representing as flonums, 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 support number objects for the entire tower of subtypes given in section 2.1. Moreover, implementations are required to support exact integer objects and exact rational number objects 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. (“Practically unlimited” means that the size and precision of these numbers should only be limited by the size of the available memory.)
Implementations may support only a limited range of inexact number objects of any type, subject to the requirements of this section. For example, an implementation may limit the range of the inexact real number objects (and therefore the range of inexact integer and rational number objects) to the dynamic range of the flonum format. Furthermore the gaps between the inexact integer objects 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 [14].
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 object 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 number objects with magnitude or significand too large to be represented in the implementation.
Positive infinity is regarded as a real (but not rational) number object that represents an indeterminate number greater than the numbers represented by all rational number objects. Negative infinity is regarded as a real (but not rational) number object that represents an indeterminate number less than the numbers represented by all rational numbers.
A NaN is regarded as a real (but not rational) number object 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 number objects for 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 number objects. These specifications are marked with “if - 0.0 is distinguished” or “implementations that distinguish - 0.0”.