2.1 Numbers

Several kinds of numbers are defined in Common Lisp. They are divided into integers; ratios; floating-point numbers, with names provided for up to four different floating-point representations; reals and complex numbers.

The number data type encompasses all kinds of numbers. For convenience, there are names for some subclasses of numbers as well. Integers and ratios are of type rational. Rational numbers and floating-point numbers are of type real. Real numbers and complex numbers are of type number.

Although the names of these types were chosen with the terminology of mathematics in mind, the correspondences are not always exact. Integers and ratios model the corresponding mathematical concepts directly. Numbers of type float may be used to approximate real numbers, both rational and irrational. The real type includes all Common Lisp numbers that represent mathematical real numbers, though there are mathematical real numbers (irrational numbers) that do not have an exact Common Lisp representation. Only real numbers may be ordered using the <, >, <=, and >= functions.

2.1.1 Integers

The integer data type is intended to represent mathematical integers. Unlike most programming languages, Common Lisp in principle imposes no limit on the magnitude of an integer; storage is automatically allocated as necessary to represent large integers.

In every Common Lisp implementation there is a range of integers that are represented more efficiently than others; each such integer is called a fixnum, and an integer that is not a fixnum is called a bignum. Common Lisp is designed to hide this distinction as much as possible; the distinction between fixnums and bignums is visible to the user in only a few places where the efficiency of representation is important. Exactly which integers are fixnums is implementation-dependent; typically they will be those integers in the range − 2n to 2n − 1, inclusive, for some n not less than 15. See most-positive-fixnum and most-negative-fixnum.

fixnum must be a supertype of the type (signed-byte 16), and additionally that the value of array-dimension-limit must be a fixnum (implying that the implementor should choose the range of fixnums to be large enough to accommodate the largest size of array to be supported). ___________________

Rationale: This specification allows programmers to declare variables in portable code to be of type fixnum for efficiency. Fixnums are guaranteed to encompass at least the set of 16-bit signed integers (compare this to the data type short int in the C programming language). In addition, any valid array index must be a fixnum, and therefore variables used to hold array indices (such as a dotimes variable) may be declared fixnum in portable code.

___________________________________________________________________________________________________________

Integers are ordinarily written in decimal notation, as a sequence of decimal digits, optionally preceded by a sign and optionally followed by a decimal point. For example:

0      ;Zero
-0      ;This always means the same as 0
+6      ;The first perfect number
28      ;The second perfect number
1024.      ;Two to the tenth power
-1      ;eπi
15511210043330985984000000.      ;25 factorial (25!), probably a bignum

Integers may be notated in radices other than ten. The notation

#nnrddddd or #nnRddddd

means the integer in radix-nn notation denoted by the digits ddddd. More precisely, one may write #, a non-empty sequence of decimal digits representing an unsigned decimal integer n, r (or R), an optional sign, and a sequence of radix-n digits, to indicate an integer written in radix n (which must be between 2 and 36, inclusive). Only legal digits for the specified radix may be used; for example, an octal number may contain only the digits 0 through 7. For digits above 9, letters of the alphabet of either case may be used in order. Binary, octal, and hexadecimal radices are useful enough to warrant the special abbreviations #b for #2r, #o for #8r, and #x for #16r. For example:

#2r11010101      ;Another way of writing 213 decimal
#b11010101      ;Ditto
#b+11010101      ;Ditto
#o325      ;Ditto, in octal radix
#xD5      ;Ditto, in hexadecimal radix
#16r+D5      ;Ditto
#o-300      ;Decimal -192, written in base 8
#3r-21010      ;Same thing in base 3
#25R-7H      ;Same thing in base 25
#xACCEDED      ;181202413, in hexadecimal radix

2.1.2 Ratios

A ratio is a number representing the mathematical ratio of two integers. Integers and ratios collectively constitute the type rational. The canonical representation of a rational number is as an integer if its value is integral, and otherwise as the ratio of two integers, the numerator and denominator, whose greatest common divisor is 1, and of which the denominator is positive (and in fact greater than 1, or else the value would be integral). A ratio is notated with / as a separator, thus: 3/5. It is possible to notate ratios in non-canonical (unreduced) forms, such as 4/6, but the Lisp function prin1 always prints the canonical form for a ratio.

If any computation produces a result that is a ratio of two integers such that the denominator evenly divides the numerator, then the result is immediately converted to the equivalent integer. This is called the rule of rational canonicalization.

Rational numbers may be written as the possibly signed quotient of decimal numerals: an optional sign followed by two non-empty sequences of digits separated by a /. This syntax may be described as follows:

ratio ::= [sign] {digit}+ / {digit}+

The second sequence may not consist entirely of zeros. For example:

2/3                    ;This is in canonical form
4/6                    ;A non-canonical form for the same number
-17/23                 ;A not very interesting ratio
-30517578125/32768     ;This is (−5∕2)15
10/5                   ;The canonical form for this is 2

To notate rational numbers in radices other than ten, one uses the same radix specifiers (one of #nnR, #O, #B, or #X) as for integers. For example:

#o-101/75          ;Octal notation for -65/61
#3r120/21          ;Ternary notation for 15/7
#Xbc/ad            ;Hexadecimal notation for 188/173
#xFADED/FACADE     ;Hexadecimal notation for 1027565/16435934

2.1.3 Floating-Point Numbers

Common Lisp allows an implementation to provide one or more kinds of floating-point number, which collectively make up the type float. Now a floating-point number is a (mathematical) rational number of the form sfbe−p, where s is + 1 or − 1, the sign; b is an integer greater than 1, the base or radix of the representation; p is a positive integer, the precision (in base-b digits) of the floating-point number; f is a positive integer between bp−1 and bp − 1 (inclusive), the significand; and e is an integer, the exponent. The value of p and the range of e depends on the implementation and on the type of floating-point number within that implementation. In addition, there is a floating-point zero; depending on the implementation, there may also be a “minus zero.” If there is no minus zero, then 0.0 and -0.0 are both interpreted as simply a floating-point zero. ______________________________________________________________________

Implementation note: The form of the above description should not be construed to require the internal representation to be in sign-magnitude form. Two’s-complement and other representations are also acceptable. Note that the radix of the internal representation may be other than 2, as on the IBM 360 and 370, which use radix 16; see float-radix.

___________________________________________________________________________________________________________

Floating-point numbers may be provided in a variety of precisions and sizes, depending on the implementation. High-quality floating-point software tends to depend critically on the precise nature of the floating-point arithmetic and so may not always be completely portable. As an aid in writing programs that are moderately portable, however, certain definitions are made here:

The precise definition of these categories is implementation-dependent. However, the rough intent is that short floating-point numbers be precise to at least four decimal places (but also have a space- efficient representation); single floating-point numbers, to at least seven decimal places; and double floating-point numbers, to at least fourteen decimal places. It is suggested that the precision (measured in bits, computed as p log 2b) and the exponent size (also measured in bits, computed as the base-2 logarithm of 1 plus the maximum exponent value) be at least as great as the values in table 2.1.


Table 2.1: Recommended Minimum Floating-Point Precision and Exponent Size
Format Minimum Precision Minimum Exponent Size
Short 13 bits 5 bits
Single 24 bits 8 bits
Double 50 bits 8 bits
Long 50 bits 8 bits

Floating-point numbers are written in either decimal fraction or computerized scientific notation: an optional sign, then a non-empty sequence of digits with an embedded decimal point, then an optional decimal exponent specification. If there is no exponent specifier, then the decimal point is required, and there must be digits after it. The exponent specifier consists of an exponent marker, an optional sign, and a non-empty sequence of digits. For preciseness, here is a modified-BNF description of floating-point notation.

floating-point-number ::= [sign] {digit}* decimal-point {digit}+ [exponent]
|  [sign] {digit}+ [decimal-point {digit}*] exponent
sign ::= + | -
decimal-point ::= .
digit ::= 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9
exponent ::= exponent-marker [sign] {digit}+
exponent-marker ::= e | s | f | d | l | E | S | F | D | L

If no exponent specifier is present, or if the exponent marker e (or E) is used, then the precise format to be used is not specified. When such a representation is read and converted to an internal floating-point data object, the format specified by the variable *read-default-float-format* is used; the initial value of this variable is single-float.

The letters s, f, d, and l (or their respective uppercase equivalents) explicitly specify the use of short, single, double, and long format, respectively.

Examples of floating-point numbers:

0.0                         ;Floating-point zero in default format
0E0                         ;Also floating-point zero in default format
-.0                         ;This may be a zero or a minus zero,
                            ; depending on the implementation
0.                          ;The integer zero, not a floating-point zero!
0.0s0                       ;A floating-point zero in short format
0s0                         ;Also a floating-point zero in short format
3.1415926535897932384d0     ;A double-format approximation to π
6.02E+23                    ;Avogadro’s number, in default format
602E+21                     ;Also Avogadro’s number, in default format
3.010299957f-1              ; log 102, in single format
-0.000000001s9              ;eπi in short format, the hard way

The internal format used for an external representation depends only on the exponent marker and not on the number of decimal digits in the external representation.

While Common Lisp provides terminology and notation sufficient to accommodate four distinct floating-point formats, not all implementations will have the means to support that many distinct formats. An implementation is therefore permitted to provide fewer than four distinct internal floating-point formats, in which case at least one of them will be “shared” by more than one of the external format names short, single, double, and long according to the following rules:

_____________________________________________________________________

Implementation note: It is recommended that an implementation provide as many distinct floating-point formats as feasible, using table 2.1 as a guideline. Ideally, short-format floating-point numbers should have an “immediate” representation that does not require heap allocation; single-format floating-point numbers should approximate IEEE proposed standard single-format floating-point numbers; and double-format floating-point numbers should approximate IEEE proposed standard double-format floating-point numbers [231716].

___________________________________________________________________________________________________________

2.1.4 Complex Numbers

Complex numbers (type complex) are represented in Cartesian form, with a real part and an imaginary part, each of which is a non-complex number (integer, ratio, or floating-point number). It should be emphasized that the parts of a complex number are not necessarily floating-point numbers; in this, Common Lisp is like PL/I and differs from Fortran. However, both parts must be of the same type: either both are rational, or both are of the same floating-point format.

Complex numbers may be notated by writing the characters #C followed by a list of the real and imaginary parts. If the two parts as notated are not of the same type, then they are converted according to the rules of floating-point contagion as described in chapter 12. (Indeed, #C(a b) is equivalent to #,(complex a b); see the description of the function complex.) For example:

#C(3.0s1 2.0s-1)     ;Real and imaginary parts are short format
#C(5 -3)             ;A Gaussian integer
#C(5/3 7.0)          ;Will be converted internally to #C(1.66666 7.0)
#C(0 1)              ;The imaginary unit, that is, i

The type of a specific complex number is indicated by a list of the word complex and the type of the components; for example, a specialized representation for complex numbers with short floating-point parts would be of type (complex short-float). The type complex encompasses all complex representations.

A complex number of type (complex rational), that is, one whose components are rational, can never have a zero imaginary part. If the result of a computation would be a complex rational with a zero imaginary part, the result is immediately converted to a non-complex rational number by taking the real part. This is called the rule of complex canonicalization. This rule does not apply to floating-point complex numbers; #C(5.0 0.0) and 5.0 are different.