- 12.1.1 Numeric Operations
- 12.1.1.1 Associativity and Commutativity in Numeric Operations
- 12.1.1.1.1 Examples of Associativity and Commutativity in Numeric Operations
- 12.1.1.2 Contagion in Numeric Operations
- 12.1.1.3 Viewing Integers as Bits and Bytes
- 12.1.1.3.1 Logical Operations on Integers
- 12.1.1.3.2 Byte Operations on Integers
- 12.1.2 Implementation-Dependent Numeric Constants
- 12.1.3 Rational Computations
- 12.1.3.1 Rule of Unbounded Rational Precision
- 12.1.3.2 Rule of Canonical Representation for Rationals
- 12.1.3.3 Rule of Float Substitutability
- 12.1.4 Floating-point Computations
- 12.1.4.1 Rule of Float and Rational Contagion
- 12.1.4.1.1 Examples of Rule of Float and Rational Contagion
- 12.1.4.2 Rule of Float Approximation
- 12.1.4.3 Rule of Float Underflow and Overflow
- 12.1.4.4 Rule of Float Precision Contagion
- 12.1.5 Complex Computations
- 12.1.5.1 Rule of Complex Substitutability
- 12.1.5.2 Rule of Complex Contagion
- 12.1.5.3 Rule of Canonical Representation for Complex Rationals
- 12.1.5.3.1 Examples of Rule of Canonical Representation for Complex Rationals
- 12.1.5.4 Principal Values and Branch Cuts
- 12.1.6 Interval Designators
- 12.1.7 Random-State Operations

Common Lisp provides a large variety of operations related to *numbers*. This section provides an overview of those operations by grouping them into categories that emphasize some of the relationships among them.

Figure 12–1 shows *operators* relating to arithmetic operations.

Figure 12–2 shows *defined names* relating to exponential, logarithmic, and trigonometric operations.

Figure 12–3 shows *operators* relating to numeric comparison and predication.

Figure 12–4 shows *defined names* relating to numeric type manipulation and coercion.

For functions that are mathematically associative (and possibly commutative), a *conforming implementation* may process the *arguments* in any manner consistent with associative (and possibly commutative) rearrangement. This does not affect the order in which the *argument* *forms* are *evaluated*; for a discussion of evaluation order, see Section 3.1.2.1.2.3 (Function Forms). What is unspecified is only the order in which the *parameter* *values* are processed. This implies that *implementations* may differ in which automatic *coercions* are applied; see Section 12.1.1.2 (Contagion in Numeric Operations).

A *conforming program* can control the order of processing explicitly by separating the operations into separate (possibly nested) *function forms*, or by writing explicit calls to *functions* that perform coercions.

Consider the following expression, in which we assume that `1.0`

and `1.0e-15`

both denote *single floats*:

(+ 1/3 2/3 1.0d0 1.0 1.0e-15)

One *conforming implementation* might process the *arguments* from left to right, first adding `1/3`

and `2/3`

to get `1`

, then converting that to a *double float* for combination with `1.0d0`

, then successively converting and adding `1.0`

and `1.0e-15`

.

Another *conforming implementation* might process the *arguments* from right to left, first performing a *single float* addition of `1.0`

and `1.0e-15`

(perhaps losing accuracy in the process), then converting the sum to a *double float* and adding `1.0d0`

, then converting `2/3`

to a *double float* and adding it, and then converting `1/3`

and adding that.

A third *conforming implementation* might first scan all the *arguments*, process all the *rationals* first to keep that part of the computation exact, then find an *argument* of the largest floating-point format among all the *arguments* and add that, and then add in all other *arguments*, converting each in turn (all in a perhaps misguided attempt to make the computation as accurate as possible).

In any case, all three strategies are legitimate.

A *conforming program* could control the order by writing, for example,

(+ (+ 1/3 2/3) (+ 1.0d0 1.0e-15) 1.0)

For information about the contagion rules for implicit coercions of *arguments* in numeric operations, see Section 12.1.4.4 (Rule of Float Precision Contagion), Section 12.1.4.1 (Rule of Float and Rational Contagion), and Section 12.1.5.2 (Rule of Complex Contagion).

Logical operations require *integers* as arguments; an error of *type* **type-error** should be signaled if an argument is supplied that is not an *integer*. *Integer* arguments to logical operations are treated as if they were represented in two’s-complement notation.

Figure 12–5 shows *defined names* relating to logical operations on numbers.

The byte-manipulation *functions* use *objects* called *byte specifiers* to designate the size and position of a specific *byte* within an *integer*. The representation of a *byte specifier* is *implementation-dependent*; it might or might not be a *number*. The *function* **byte** will construct a *byte specifier*, which various other byte-manipulation *functions* will accept.

Figure 12–6 shows *defined names* relating to manipulating *bytes* of *numbers*.

Figure 12–7 shows *defined names* relating to *implementation-dependent* details about *numbers*.

The rules in this section apply to *rational* computations.

Rational computations cannot overflow in the usual sense (though there may not be enough storage to represent a result), since *integers* and *ratios* may in principle be of any magnitude.

If any computation produces a result that is a mathematical ratio of two integers such that the denominator evenly divides the numerator, then the result is converted to the equivalent *integer*.

If the denominator does not evenly divide the numerator, the canonical representation of a *rational* number is as the *ratio* that numerator and that denominator, where the greatest common divisor of the numerator and denominator is one, and where the denominator is positive and greater than one.

When used as input (in the default syntax), the notation `-0`

always denotes the *integer* `0`

. A *conforming implementation* must not have a representation of “minus zero” for *integers* that is distinct from its representation of zero for *integers*. However, such a distinction is possible for *floats*; see the *type* **float**.

When the arguments to an irrational mathematical *function* are all *rational* and the true mathematical result is also (mathematically) rational, then unless otherwise noted an implementation is free to return either an accurate *rational* result or a *single float* approximation. If the arguments are all *rational* but the result cannot be expressed as a *rational* number, then a *single float* approximation is always returned.

If the arguments to an irrational mathematical *function* are all of type `(or rational (complex rational))`

and the true mathematical result is (mathematically) a complex number with rational real and imaginary parts, then unless otherwise noted an implementation is free to return either an accurate result of type `(or rational (complex rational))`

or a *single float* (permissible only if the imaginary part of the true mathematical result is zero) or `(complex single-float)`

. If the arguments are all of type `(or rational (complex rational))`

but the result cannot be expressed as a *rational* or *complex rational*, then the returned value will be of *type* **single-float** (permissible only if the imaginary part of the true mathematical result is zero) or `(complex single-float)`

.

Float substitutability applies neither to the rational *functions* **+**, **-**, *****, and **/** nor to the related *operators* **1+**, **1-**, **incf**, **decf**, and **conjugate**. For rational *functions*, if all arguments are *rational*, then the result is *rational*; if all arguments are of type `(or rational (complex rational))`

, then the result is of type `(or rational (complex rational))`

.

Function | Sample Results |
---|---|

abs | `(abs #c(3 4)) → 5 ` |

acos | `(acos 1) → 0 ` |

acosh | `(acosh 1) → 0 ` |

asin | `(asin 0) → 0 ` |

asinh | `(asinh 0) → 0 ` |

atan | `(atan 0) → 0 ` |

atanh | `(atanh 0) → 0 ` |

cis | `(cis 0) → 1 ` |

cos | `(cos 0) → 1 ` |

cosh | `(cosh 0) → 1 ` |

exp | `(exp 0) → 1 ` |

expt | `(expt 8 1/3) → 2 ` |

log | `(log 1) → 0 ` |

`(log 8 2) → 3 ` | |

phase | `(phase 7) → 0 ` |

signum | `(signum #c(3 4)) → #c(3/5 4/5) ` |

sin | `(sin 0) → 0 ` |

sinh | `(sinh 0) → 0 ` |

sqrt | `(sqrt 4) → 2 ` |

`(sqrt 9/16) → 3/4 ` | |

tan | `(tan 0) → 0 ` |

tanh | `(tanh 0) → 0 ` |

The following rules apply to floating point computations.

When *rationals* and *floats* are combined by a numerical function, the *rational* is first converted to a *float* of the same format. For *functions* such as **+** that take more than two arguments, it is permitted that part of the operation be carried out exactly using *rationals* and the rest be done using floating-point arithmetic.

When *rationals* and *floats* are compared by a numerical function, the *function* **rational** is effectively called to convert the *float* to a *rational* and then an exact comparison is performed. In the case of *complex* numbers, the real and imaginary parts are effectively handled individually.

;;;; Combining rationals with floats. ;;; This example assumes an implementation in which ;;; (float-radix 0.5) is 2 (as in IEEE) or 16 (as in IBM/360), ;;; or else some other implementation in which 1/2 has an exact ;;; representation in floating point. (+ 1/2 0.5) → 1.0 (- 1/2 0.5d0) → 0.0d0 (+ 0.5 -0.5 1/2) → 0.5 ;;;; Comparing rationals with floats. ;;; This example assumes an implementation in which the default float ;;; format is IEEE single-float, IEEE double-float, or some other format ;;; in which 5/7 is rounded upwards by FLOAT. (< 5/7 (float 5/7)) →true(< 5/7 (rational (float 5/7))) →true(< (float 5/7) (float 5/7)) →false

Computations with *floats* are only approximate, although they are described as if the results were mathematically accurate. Two mathematically identical expressions may be computationally different because of errors inherent in the floating-point approximation process. The precision of a *float* is not necessarily correlated with the accuracy of that number. For instance, 3.142857142857142857 is a more precise approximation to π than 3.14159, but the latter is more accurate. The precision refers to the number of bits retained in the representation. When an operation combines a *short float* with a *long float*, the result will be a *long float*. Common Lisp functions assume that the accuracy of arguments to them does not exceed their precision. Therefore when two *small floats* are combined, the result is a *small float*. Common Lisp functions never convert automatically from a larger size to a smaller one.

An error of *type* **floating-point-overflow** or **floating-point-underflow** should be signaled if a floating-point computation causes exponent overflow or underflow, respectively.

The result of a numerical function is a *float* of the largest format among all the floating-point arguments to the *function*.

The following rules apply to *complex* computations:

Except during the execution of irrational and transcendental *functions*, no numerical *function* ever *yields* a *complex* unless one or more of its *arguments* is a *complex*.

When a *real* and a *complex* are both part of a computation, the *real* is first converted to a *complex* by providing an imaginary part of `0`

.

If the result of any computation would be a *complex* number whose real part is of *type* **rational** and whose imaginary part is zero, the result is converted to the *rational* which is the real part. This rule does not apply to *complex* numbers whose parts are *floats*. For example, `#C(5 0)`

and `5`

are not *different* *objects* in Common Lisp(they are always the *same* under **eql**); `#C(5.0 0.0)`

and `5.0`

are always *different* *objects* in Common Lisp (they are never the *same* under **eql**, although they are the *same* under **equalp** and **=**).

#c(1.0 1.0) → #C(1.0 1.0) #c(0.0 0.0) → #C(0.0 0.0) #c(1.0 1) → #C(1.0 1.0) #c(0.0 0) → #C(0.0 0.0) #c(1 1) → #C(1 1) #c(0 0) → 0 (typep #c(1 1) '(complex (eql 1))) →true(typep #c(0 0) '(complex (eql 0))) →false

Many of the irrational and transcendental functions are multiply defined in the complex domain; for example, there are in general an infinite number of complex values for the logarithm function. In each such case, a *principal* *value* must be chosen for the function to return. In general, such values cannot be chosen so as to make the range continuous; lines in the domain called branch cuts must be defined, which in turn define the discontinuities in the range. Common Lisp defines the branch cuts, *principal* *values*, and boundary conditions for the complex functions following “Principal Values and Branch Cuts in Complex APL.” The branch cut rules that apply to each function are located with the description of that function.

Figure 12–9 lists the identities that are obeyed throughout the applicable portion of the complex domain, even on the branch cuts:

sin i z = i sinh z | sinh i z = i sin z | arctan i z = i arctanh z |

cos i z = cosh z | cosh i z = cos z | arcsinh i z = i arcsin z |

tan i z = i tanh z | arcsin i z = i arcsinh z | arctanh i z = i arctan z |

The quadrant numbers referred to in the discussions of branch cuts are as illustrated in Figure 12–10.

The *compound type specifier* form of the numeric *type specifiers* permit the user to specify an interval on the real number line which describe a *subtype* of the *type* which would be described by the corresponding *atomic type specifier*. A *subtype* of some *type* `T` is specified using an ordered pair of *objects* called *interval designators* for *type* `T`.

The first of the two *interval designators* for *type* `T` can be any of the following:

- a number
`N`of*type*`T` This denotes a lower inclusive bound of

`N`. That is,*elements*of the*subtype*of`T`will be greater than or equal to`N`.- a
*singleton**list*whose*element*is a number`M`of*type*`T` This denotes a lower exclusive bound of

`M`. That is,*elements*of the*subtype*of`T`will be greater than`M`.- the symbol
***** This denotes the absence of a lower bound on the interval.

The second of the two *interval designators* for *type* `T` can be any of the following:

- a number
`N`of*type*`T` This denotes an upper inclusive bound of

`N`. That is,*elements*of the*subtype*of`T`will be less than or equal to`N`.- a
*singleton**list*whose*element*is a number`M`of*type*`T` This denotes an upper exclusive bound of

`M`. That is,*elements*of the*subtype*of`T`will be less than`M`.- the symbol
***** This denotes the absence of an upper bound on the interval.

Figure 12–11 lists some *defined names* that are applicable to *random states*.