## 12.2. Number Concepts [sec_12-1]

12.2.1. Numeric Operations
12.2.1.2. Function `DECODE-FLOAT`
12.2.1.3. Boolean Operations
12.2.1.4. Byte Operations on Integers
12.2.1.5. Floating Point Arithmetics
12.2.2. Implementation-Dependent Numeric Constants
12.2.2.1. Fixnum Limits
12.2.2.2. Bignum Limits
12.2.2.3. Float Limits
12.2.3. Rule of Float Substitutability
12.2.4. Floating-point Computations
12.2.4.1. Rule of Float Precision Contagion
12.2.4.2. Rule of Float and Rational Contagion
12.2.5. Complex Computations
12.2.6. Rule of Canonical Representation for Complex Rationals
12.2.7. Random-State Operations

### 12.2.1. Numeric Operations [sec_12-1-1]

Function `EXT:!` `(EXT:! n)` returns the factorial of `n`, `n` being a nonnegative `INTEGER`.

Function `EXT:EXQUO``(EXT:EXQUO x y)` returns the integer quotient `x/y` of two integers `x`,`y`, and `SIGNAL`s an `ERROR` when the quotient is not integer. (This is more efficient than `/`.)

Function `EXT:XGCD``(EXT:XGCD x1 ... xn)` returns the values `l`, `k1`, ..., `kn`, where `l` is the greatest common divisor of the integers `x1`, ..., `xn`, and `k1`, ..., `kn` are the integer coefficients such that

````l` = (`GCD` `x1` ... `xn`)
= (+ (* `k1` `x1`) ... (* `kn` `xn`))
```

Function `EXT:MOD-EXPT``(EXT:MOD-EXPT k l m)` is equivalent to `(MOD (EXPT k l) m)` except it is more efficient for very large arguments.

#### 12.2.1.2. Function `DECODE-FLOAT`

`FLOAT-RADIX` always returns 2.

`(FLOAT-DIGITS number digits)` coerces `number` (a `REAL`) to a floating point number with at least `digits` mantissa digits. The following always evaluates to `T`:

```(`>=` (`FLOAT-DIGITS` (`FLOAT-DIGITS` `number` `digits`)) `digits`)
```

#### 12.2.1.4. Byte Operations on Integers [sec_12-1-1-3-2]

Byte specifiers are objects of built-in type BYTE, not `INTEGER`s.

#### 12.2.1.5. Floating Point Arithmetics

Function `EXPT``(EXPT base exponent)` is not very precise if `exponent` has a large absolute value.

Function `LOG``(LOG number base)` `SIGNAL`s an `ERROR` if `base = 1`.

Constant `PI`. The value of `PI` is a `LONG-FLOAT` with the precision given by `(EXT:LONG-FLOAT-DIGITS)`. When this precision is changed, the value of `PI` is automatically recomputed. Therefore `PI` is not a constant variable.

Function `UPGRADED-COMPLEX-PART-TYPE`. When the argument is not a recognizable subtype or `REAL`, `UPGRADED-COMPLEX-PART-TYPE` `SIGNAL`s an `ERROR`, otherwise it returns its argument (even though a `COMPLEX` number in CLISP can always have `REALPART` and `IMAGPART` of any type) because it allows the most precise type inference.

Variable `CUSTOM:*DEFAULT-FLOAT-FORMAT*`. When rational numbers are to be converted to floats (due to `FLOAT`, `COERCE`, `SQRT` or a transcendental function), the result type is given by the variable `CUSTOM:*DEFAULT-FLOAT-FORMAT*`. See also `*READ-DEFAULT-FLOAT-FORMAT*`.

Macro `EXT:WITHOUT-FLOATING-POINT-UNDERFLOW`. The macro `(EXT:WITHOUT-FLOATING-POINT-UNDERFLOW {form}*)` executes the `form`s, with errors of type `FLOATING-POINT-UNDERFLOW` inhibited. Floating point operations will silently return zero instead of `SIGNAL`ing an `ERROR` of type `FLOATING-POINT-UNDERFLOW`.

Condition `FLOATING-POINT-INVALID-OPERATION`. This `CONDITION` is never `SIGNAL`ed by CLISP.

Condition `FLOATING-POINT-INEXACT`. This `CONDITION` is never `SIGNAL`ed by CLISP.

### 12.2.2. Implementation-Dependent Numeric Constants [sec_12-1-2]

#### 12.2.2.1. Fixnum Limits

Table 12.2. Fixnum limits

CPU type32-bit CPU64-bit CPU
`MOST-POSITIVE-FIXNUM`224-1 = 16777215248-1 = 281474976710655
`MOST-NEGATIVE-FIXNUM`-224 = -16777216-248 = -281474976710656

#### 12.2.2.2. Bignum Limits

`BIGNUM`s are limited in size. Their maximum size is `32*(216-2)=2097088` bits. The largest representable `BIGNUM` is therefore `22097088-1`.

#### 12.2.2.3. Float Limits

Together with `PI`, the other `LONG-FLOAT` constants

 `LEAST-NEGATIVE-LONG-FLOAT` `LONG-FLOAT-EPSILON` `LEAST-NEGATIVE-NORMALIZED-LONG-FLOAT` `LONG-FLOAT-NEGATIVE-EPSILON` `LEAST-POSITIVE-LONG-FLOAT` `MOST-NEGATIVE-LONG-FLOAT` `LEAST-POSITIVE-NORMALIZED-LONG-FLOAT` `MOST-POSITIVE-LONG-FLOAT`

are recomputed whenever `(EXT:LONG-FLOAT-DIGITS)` is `SETF`ed. They are not constant variables.

### Warning

Since the exponent of a `LONG-FLOAT` is a signed 32-bits integer, `MOST-POSITIVE-LONG-FLOAT` is about `2231`, which is much larger that the largest representable `BIGNUM`, which is less than `2221`. This, obviously, means that `ROUND`, `TRUNCATE`, `FLOOR` and `CEILING` `SIGNAL`s an `ERROR` on large `LONG-FLOAT`s. Less obviously, this means that ```(FORMAT NIL "~E" MOST-POSITIVE-LONG-FLOAT)``` also fails.

### 12.2.3. Rule of Float Substitutability [sec_12-1-3-3]

When a mathematical function may return an exact (`RATIONAL`) or inexact (`FLOAT`) result, it always returns the exact result.

### 12.2.4. Floating-point Computations [sec_12-1-4]

There are four floating point types: `SHORT-FLOAT`, `SINGLE-FLOAT`, `DOUBLE-FLOAT` and `LONG-FLOAT`:

typesignmantissaexponentcomment
`SHORT-FLOAT`1 bit16+1 bits8 bitsimmediate
`SINGLE-FLOAT`1 bit23+1 bits8 bitsIEEE 754
`DOUBLE-FLOAT`1 bit52+1 bits11 bitsIEEE 754
`LONG-FLOAT`1 bit>=64 bits32 bitsvariable length

The single and double float formats are those of the IEEE 754 Standard for Binary Floating-Point Arithmetic, except that CLISP does not support features like `±0`, `±inf`, `NaN`, gradual underflow, etc. Common Lisp does not make use of these features, so, to reduce portability problems, CLISP by design returns the same floating point results on all platforms (CLISP has a floating-point emulation built in for platforms that do not support IEEE 754). Note that

• When you got a `NaN` in your program, your program is broken, so you will spend time determining where the `NaN` came from. It is better to `SIGNAL` an `ERROR` in this case.
• When you got unnormalized floats in your program, your results will have a greatly reduced accuracy anyway. Since CLISP has the means to cope with this - `LONG-FLOAT`s of variable precision - it does not need unnormalized floats.

This is why `*FEATURES*` does not contain the `:IEEE-FLOATING-POINT` keyword.

Arbitrary Precision Floats. `LONG-FLOAT`s have variable mantissa length, which is a multiple of 16 (or 32, depending on the word size of the processor). The default length used when `LONG-FLOAT`s are `READ` is given by the place `(EXT:LONG-FLOAT-DIGITS)`. It can be set by `(SETF (EXT:LONG-FLOAT-DIGITS) n)`, where `n` is a positive `INTEGER`. E.g., ```(SETF (EXT:LONG-FLOAT-DIGITS) 3322)``` sets the default precision of `LONG-FLOAT`s to about 1000 decimal digits.

#### 12.2.4.1. Rule of Float Precision Contagion [sec_12-1-4-4]

The floating point contagion is controlled by the variable `CUSTOM:*FLOATING-POINT-CONTAGION-ANSI*`. When it is non-`NIL`, contagion is done as per the [ANSI CL standard]: `SHORT-FLOAT``SINGLE-FLOAT``DOUBLE-FLOAT``LONG-FLOAT`.

Rationale:
See it pragmatically: save what you can and let others worry about the rest.
Brief:
Common Lisp knows the number's precision, not accuracy, so preserving the precision can be accomplished reliably, while anything relating to the accuracy is just a speculation - only the user (programmer) knows what it is in each case.
Detailed:
A computer float is an approximation of a real number. One can think of it as a random variable with the mean equal to itself and standard deviation equal to half the last significant digit. E.g., `1.5` is actually `1.5±0.05`. Consider adding `1.5` and `1.75`. [ANSI CL standard] requires that `(+ 1.5 1.75)` return 3.25, while traditional CLISP would return 3.3. The implied random variables are: `3.25±0.005` and `3.3±0.05`. Note that the traditional CLISP way does lie about the mean: the mean is `3.25` and nothing else, while the standard way could be lying about the deviation (accuracy): if the implied accuracy of `1.5` (i.e., 0.05) is its actual accuracy, then the accuracy of the result cannot be smaller that that. Therefore, since Common Lisp has no way of knowing the actual accuracy, [ANSI CL standard] (and all the other standard engineering programming languages, like C, Fortran etc) decided that keeping the accuracy correct is the business of the programmer, while the language should preserve what it can - the precision.
Experience:
Rounding errors accumulate, and if a computation is conducted with insufficient precision, an outright incorrect result can be returned. (E.g., ```E(x2) - E(x)2``` can be negative!) The user should not mix floats of different precision (that's what `CUSTOM:*WARN-ON-FLOATING-POINT-CONTAGION*` is for), but one should not be penalized for this too harshly.

When `CUSTOM:*FLOATING-POINT-CONTAGION-ANSI*` is `NIL`, the traditional CLISP method is used, namely the result of an arithmetic operation whose arguments are of different float types is rounded to the float format of the shortest (least precise) of the arguments: `RATIONAL``LONG-FLOAT``DOUBLE-FLOAT``SINGLE-FLOAT``SHORT-FLOAT` (in contrast to [sec_12-1-4-4]!)

Rationale:
See it mathematically. Add intervals: ```{1.0 ± 1e-8} + {1.0 ± 1e-16} = {2.0 ± 1e-8}```. So, if we add `1.0s0` and `1.0d0`, we should get `2.0s0`.
Brief:
Do not suggest high accuracy of a result by giving it a precision that is greater than its accuracy.
Example:
`(- (+ 1.7 PI) PI)` should not return 1.700000726342836417234L0, it should return 1.7f0 (or 1.700001f0 if there were rounding errors).
Experience:
If in a computation using thousands of `SHORT-FLOAT`s, a `LONG-FLOAT` (like `PI`) happens to be used, the long precision should not propagate throughout all the intermediate values. Otherwise, the long result would look precise, but its accuracy is only that of a `SHORT-FLOAT`; furthermore much computation time would be lost by calculating with `LONG-FLOAT`s when only `SHORT-FLOAT`s would be needed.
##### Variable `CUSTOM:*WARN-ON-FLOATING-POINT-CONTAGION*`

If the variable `CUSTOM:*WARN-ON-FLOATING-POINT-CONTAGION*` is non-`NIL`, a `WARNING` is emitted for every coercion involving different floating-point types. As explained above, float precision contagion is not a good idea. You can avoid the contagion by doing all your computations with the same floating-point type (and using `FLOAT` to convert all constants, e.g., `PI`, to your preferred type).

This variable helps you eliminate all occurrences of float precision contagion: set it to `T` to have CLISP `SIGNAL` a `WARNING` on float precision contagion; set it to `ERROR` to have CLISP `SIGNAL` an `ERROR` on float precision contagion, so that you can look at the stack backtrace.

#### 12.2.4.2. Rule of Float and Rational Contagion [sec_12-1-4-1]

The contagion between floating point and rational numbers is controlled by the variable `CUSTOM:*FLOATING-POINT-RATIONAL-CONTAGION-ANSI*`. When it is non-`NIL`, contagion is done as per the [ANSI CL standard]: `RATIONAL``FLOAT`.

When `CUSTOM:*FLOATING-POINT-RATIONAL-CONTAGION-ANSI*` is `NIL`, the traditional CLISP method is used, namely if the result is mathematically an exact rational number, this rational number is returned (in contrast to [sec_12-1-4-1]!)

`CUSTOM:*FLOATING-POINT-RATIONAL-CONTAGION-ANSI*` has an effect only in those few cases when the mathematical result is exact although one of the arguments is a floating-point number, such as `(* 0 1.618)`, `(/ 0 1.618)`, `(ATAN 0 1.0)`, `(EXPT 2.0 0)`, `(PHASE 2.718)`.

##### Variable `CUSTOM:*WARN-ON-FLOATING-POINT-RATIONAL-CONTAGION*`

If the variable `CUSTOM:*WARN-ON-FLOATING-POINT-RATIONAL-CONTAGION*` is non-`NIL`, a `WARNING` is emitted for every avoidable coercion from a rational number to a floating-point number. You can avoid such coercions by calling `FLOAT` to convert the particular rational numbers to your preferred floating-point type.

This variable helps you eliminate all occurrences of avoidable coercions to a floating-point number when a rational number result would be possible: set it to `T` to have CLISP `SIGNAL` a `WARNING` in such situations; set it to `ERROR` to have CLISP `SIGNAL` an `ERROR` in such situations, so that you can look at the stack backtrace.

##### Variable `CUSTOM:*PHASE-ANSI*`

A similar variable, `CUSTOM:*PHASE-ANSI*`, controls the return value of `PHASE` when the argument is an exact nonnegative `REAL`. Namely, if `CUSTOM:*PHASE-ANSI*` is non-`NIL`, it returns a floating-point zero; if `CUSTOM:*PHASE-ANSI*` is `NIL`, it returns an exact zero. Example: `(PHASE 2/3)`

### 12.2.5. Complex Computations [sec_12-1-5]

Complex numbers can have a real part and an imaginary part of different types. For example, `(SQRT -9.0)` evaluates to the number `#C(0 3.0)`, which has a real part of exactly `0`, not only `0.0` (which would mean approximately 0).

The type specifier for this is ```(COMPLEX INTEGER SINGLE-FLOAT)```, and ```(COMPLEX type-of-real-part type-of-imaginary-part)``` in general.

The type specifier ```(COMPLEX type)``` is equivalent to ```(COMPLEX type type)```.

### 12.2.6. Rule of Canonical Representation for Complex Rationals [sec_12-1-5-3]

Complex numbers can have a real part and an imaginary part of different types. If the imaginary part is `EQL` to `0`, the number is automatically converted to a real number.

This has the advantage that `(LET ((x (SQRT -9.0))) (* x x))` - instead of evaluating to `#C(-9.0 0.0)`, with `x` = `#C(0.0 3.0)` - evaluates to `#C(-9.0 0)` = `-9.0`, with `x` = `#C(0 3.0)`.

### 12.2.7. Random-State Operations [sec_12-1-7]

To ease reproducibility, the variable `*RANDOM-STATE*` is initialized to the same value on each invocation, so that

``\$` clisp -norc `-x` '(`RANDOM` 1s0)'`

will always print the same number.

If you want a new random state on each invocation, you can arrange for that by using init function:

````\$` clisp -norc `-x` '(`EXT:SAVEINITMEM` "foo" :init-function (`LAMBDA` () (`SETQ` `*RANDOM-STATE*` (`MAKE-RANDOM-STATE` `T`))))'
`\$` clisp -norc `-M` foo.mem `-x` '(`RANDOM` 1s0)'```

or by placing ```(SETQ *RANDOM-STATE* (MAKE-RANDOM-STATE T))``` into your RC file.