Numerics¶
Overview¶
It is important to distinguish between mathematical numbers, the Cozenage numbers that attempt to model them, the machine representations used to implement those numbers, and the notations used to write numeric literals in source code.
From a user’s perspective, Cozenage numbers are abstract values that behave according to mathematical rules as closely as practical, while hiding most details of how they are represented internally.
Numeric Types in Cozenage¶
Cozenage implements four distinct object types to represent mathematical values:
Integers
Rationals
Reals
Complex numbers
Each of these types corresponds to a well-known mathematical category, and each has a clear meaning independent of Cozenage.
The Numeric Tower¶
Mathematically, numbers are arranged into a tower of subtypes, in which each level is a subset of the level above it:
number
complex number
real number
rational number
integer
This means that every integer is also a rational number, every rational number is also a real number, and every real number is also a complex number.
For example, the mathematical number 3 is:
an integer,
a rational number (3 = 3/1),
a real number (3 = 3.0)
a complex number (3 + 0i).
The same is true of the Cozenage numbers that model 3.
For Cozenage numbers, these categories are identified by the predicates number?, complex?, real?, rational?, and integer?. It is important to note that these predicates response to a number’s mathematical value, and not the number’s representation:
--> (integer? 3.1)
#false
--> (integer? 3.0)
#true
--> (integer? 3+0i)
#true
--> (integer? 3+1i)
#false
--> (rational? 3)
#true
--> (real? 3)
#true
--> (complex? 3)
#true
number? is essentially an alias for complex?, and will return true for any numeric object.
--> (number? 3) #true --> (number? 1/3) #true --> (number? 23.364) #true --> (number? 23-45i) #true --> (number? "1000") ; "1000" is a string #false
Mathematical Meaning of the Numeric Types¶
The following informal definitions describe what each numeric type represents mathematically.
Integers
Integers are whole numbers with no fractional part. They include positive numbers, negative numbers, and zero.
Examples:
0
42
-7
Rationals
Rational numbers are numbers that can be expressed as the ratio of two integers, where the denominator is non-zero. This includes all integers, since any integer n can be written as n/1.
Examples:
1/2
-7/3
3/1
Reals
Real numbers represent values along the continuous number line. In Cozenage, reals are typically written using decimal notation and may represent values that cannot be expressed exactly as rational numbers.
Examples:
3.0
2.71828
-0.5
Complex Numbers
Complex numbers consist of a real part and an imaginary part, usually written in the form a + bi, where i is the square root of −1.
Examples:
3+0i
1+2i
-4.5-0.1i
Representation Independence¶
There is no simple relationship between a number’s type and its representation inside a computer.
Although Cozenage offers four different representations of the number 3:
3 ; integer
3/1 ; rational
3.0 ; real
3+0i ; complex
these different representations denote the same mathematical integer.
Cozenage’s numerical operations treat numbers as abstract data, as independent of their representation as possible. This means, with a few exceptions that will be noted elsewhere, numeric procedures will work on any of the above representations, and on any combination of them.
For example, arithmetic procedures do not require operands to have the same numeric type.
Numeric Literal Syntax¶
Cozenage provides several ways to write numeric literals. These notations affect how numbers are read, but not the abstract numeric value they represent.
Default Base (Decimal)¶
By default, numeric literals are interpreted as base-10 (decimal) numbers.
Examples:
10
255
-42
Explicit Radix Prefixes¶
Cozenage also allows numeric literals to specify an explicit base using a prefix:
#b for binary (base 2)
#o for octal (base 8)
#d for decimal (base 10)
#x for hexadecimal (base 16)
Examples:
#b1010 ; binary 10
#o377 ; octal 255
#d42 ; decimal 42
#xFF ; hexadecimal 255
All of these literals denote exact integer values, regardless of the base used to write them.
Exact and Inexact Numbers¶
Cozenage distinguishes between exact and inexact numbers.
Exact numbers represent values with no loss of precision.
Inexact numbers represent values that may be approximations.
Integers and rational numbers are typically exact. Real numbers written with decimal notation are often inexact.
Examples:
1/3 ; exact rational
3 ; exact integer
3.0 ; inexact real
Exactness Prefixes¶
Numeric literals may explicitly specify exactness using prefixes:
#e forces an exact number
#i forces an inexact number
Examples:
#e3.0 ; exact representation of 3
#i3 ; inexact representation of 3
These prefixes control how a number is interpreted when it is read, not how it is printed. The REPL (and output procedures such as display and write) always represent numbers in base 10 decimal form.
Mixed Numeric Computations¶
When arithmetic combines exact and inexact numbers, the result is generally inexact. This reflects the idea that an approximate input produces an approximate result. Operations on inexact numbers are said to be contagious, in that an operation that includes even one inexact input will produce an inexact result. While this may sound disconcerting at first, it is important to understand that an inexact value is typically correct to within the limits of machine representation. Outside of rigorous symbolic or high-precision scientific computation, inexact numbers are entirely appropriate and expected for the vast majority of practical programs.
Example:
--> (+ 1 2.0)
3.0
Summary¶
Cozenage numbers model mathematical numbers using a small set of well-defined numeric types. Integers, rationals, reals, and complex numbers form a numeric tower in which each category is a subset of the one above it.
Numeric literals provide flexible notation, including different bases and explicit control over exactness. By treating numbers as abstract values rather than fixed representations, Cozenage allows numeric code to be written in a clear and mathematically natural style.
Numeric procedures¶
addition¶
- (+ n ...)
Returns the sum of all arguments. Applies numeric promotion as needed across the numeric tower. If no arguments are provided, returns the additive identity
0. If exactly one argument is provided, it is returned unchanged.- Parameters:
n (number) – Zero or more numbers to sum.
- Returns:
The sum of all arguments, or
0if no arguments are given.- Return type:
number
Example:
--> (+) 0 --> (+ 5) 5 --> (+ 1 2 3) 6 --> (+ 1/3 1/6) 1/2 --> (+ 1 1.5) 2.5 --> (+ 1+2i 3+4i) 4+6i
subtraction¶
- (- n1 [n2 ...])
When called with a single argument, returns the negation of n1. When called with two or more arguments, returns the result of subtracting each successive argument from n1. Applies numeric promotion as needed across the numeric tower.
- Parameters:
n1 (number) – The number to negate, or the minuend in a subtraction.
n2 (number) – One or more numbers to subtract from n1.
- Returns:
The negation of n1, or the result of subtracting all subsequent arguments from n1.
- Return type:
number
Example:
--> (- 5) -5 --> (- 10 3) 7 --> (- 10 3 2) 5 --> (- 1/2) -1/2 --> (- 1+2i) -1-2i
multiplication¶
- (* n ...)
Returns the product of all arguments. Applies numeric promotion as needed across the numeric tower. If no arguments are provided, returns the multiplicative identity
1. If exactly one argument is provided, it is returned unchanged.- Parameters:
n (number) – Zero or more numbers to multiply.
- Returns:
The product of all arguments, or
1if no arguments are given.- Return type:
number
Example:
--> (*) 1 --> (* 5) 5 --> (* 2 3 4) 24 --> (* 1/3 3) 1 --> (* 2 1.5) 3.0 --> (* 1+2i 3+4i) -5+10i
division¶
- (/ n1 [n2 ...])
When called with a single argument, returns the reciprocal of n1. When called with two or more arguments, returns the result of dividing n1 by each successive argument. Applies numeric promotion as needed across the numeric tower.
Integer division produces a rational result when the quotient is not exact (e.g.
(/ 10 3)yields10/3). Division of an integer by an integer that divides evenly yields an integer. Dividing by integer zero raises an error. Dividing0.0by0.0returns+nan.0per IEEE 754.- Parameters:
n1 (number) – The number to take the reciprocal of, or the dividend.
n2 (number) – One or more divisors.
- Returns:
The reciprocal of n1, or the result of dividing n1 by all subsequent arguments.
- Return type:
number
Example:
--> (/ 2) 1/2 --> (/ 1.0) 1.0 --> (/ 10 2) 5 --> (/ 10 3) 10/3 --> (/ 1 3 3) 1/9 --> (/ 1+2i) 1/5-2/5i
abs¶
- (abs x)
Returns the absolute value of x. For complex numbers, returns the magnitude
√(a² + b²)as an inexact real number. For all other numeric types, returns a non-negative value of the same type as x.- Parameters:
x (number) – The number to take the absolute value of.
- Returns:
The absolute value or magnitude of x.
- Return type:
number
Example:
--> (abs -7) 7 --> (abs 3.14) 3.14 --> (abs -1/3) 1/3 --> (abs 3+4i) 5.0
expt¶
- (expt z1 z2)
Returns z1 raised to the power z2. The type of the result depends on the types of the arguments:
If either argument is
0(exactly),(expt 0 z2)returns0and(expt z1 0)returns1.If z1 is a non-negative real and z2 is negative, an exact rational is returned.
If z1 is a negative real and z2 is a non-integer, the result is a complex number.
If z1 is a bignum, z2 must be an exact integer and must not exceed the platform
INT_MAX.
- Parameters:
z1 (number) – The base.
z2 (number) – The exponent.
- Returns:
z1 raised to the power z2.
- Return type:
number
Example:
--> (expt 2 10) 1024 --> (expt 2 -3) 1/8 --> (expt 2.0 10) 1024.0 --> (expt -1 1/2) 0.0+1.0i --> (expt 1+2i 2) -3.0+4.0i --> (expt 0 0) 1
modulo¶
- (modulo n1 n2)
Returns the remainder of dividing n1 by n2, with the result having the same sign as n2 (the divisor). Both arguments must be integers.
- Parameters:
n1 (integer) – The dividend.
n2 (integer) – The divisor.
- Returns:
The modulo of n1 and n2, with the sign of n2.
- Return type:
integer
Example:
--> (modulo 10 3) 1 --> (modulo -10 3) 2 --> (modulo 10 -3) -2 --> (modulo -10 -3) -1
quotient¶
- (quotient n1 n2)
Returns the integer quotient of dividing n1 by n2, truncating toward zero. Both arguments must be integers.
- Parameters:
n1 (integer) – The dividend.
n2 (integer) – The divisor.
- Returns:
The integer quotient of n1 and n2, truncated toward zero.
- Return type:
integer
Example:
--> (quotient 10 3) 3 --> (quotient -10 3) -3 --> (quotient 10 -3) -3 --> (quotient -10 -3) 3
remainder¶
- (remainder n1 n2)
Returns the remainder of dividing n1 by n2, with the result having the same sign as n1 (the dividend). Both arguments must be integers.
- Parameters:
n1 (integer) – The dividend.
n2 (integer) – The divisor.
- Returns:
The remainder of n1 divided by n2, with the sign of n1.
- Return type:
integer
Example:
--> (remainder 10 3) 1 --> (remainder -10 3) -1 --> (remainder 10 -3) 1 --> (remainder -10 -3) -1
max¶
- (max x1 x2 ...)
Returns the largest of its arguments. All arguments must be real numbers; complex numbers are not permitted.
- Parameters:
x1 (real) – One or more real numbers to compare.
- Returns:
The largest argument.
- Return type:
real
Example:
--> (max 1 2 3) 3 --> (max -5 0 5) 5 --> (max 1/2 0.4 3/5) 0.6 --> (max 42) 42
min¶
- (min x1 x2 ...)
Returns the smallest of its arguments. All arguments must be real numbers; complex numbers are not permitted.
- Parameters:
x1 (real) – One or more real numbers to compare.
- Returns:
The smallest argument.
- Return type:
real
Example:
--> (min 1 2 3) 1 --> (min -5 0 5) -5 --> (min 1/2 0.4 3/5) 0.4 --> (min 42) 42
floor¶
- (floor x)
Returns the largest integer not larger than x. If x is an exact integer or bignum, it is returned unchanged.
- Parameters:
x (real) – A real number.
- Returns:
The largest integer not larger than x.
- Return type:
integer
Example:
--> (floor 3.7) 3 --> (floor -3.7) -4 --> (floor 7/2) 3 --> (floor 4) 4
ceiling¶
- (ceiling x)
Returns the smallest integer not smaller than x. If x is an exact integer or bignum, it is returned unchanged.
- Parameters:
x (real) – A real number.
- Returns:
The smallest integer not smaller than x.
- Return type:
integer
Example:
--> (ceiling 3.2) 4 --> (ceiling -3.2) -3 --> (ceiling 7/2) 4 --> (ceiling 4) 4
round¶
- (round x)
Returns the closest integer to x, rounding halfway values to the nearest even integer. If x is an exact integer or bignum, it is returned unchanged.
- Parameters:
x (real) – A real number.
- Returns:
The closest integer to x.
- Return type:
integer
Example:
--> (round 3.2) 3 --> (round 3.7) 4 --> (round 3.5) 4 --> (round 4.5) 4 --> (round -3.5) -4
truncate¶
- (truncate x)
Returns the integer closest to x whose absolute value is not larger than that of x; i.e., rounds toward zero. If x is an exact integer or bignum, it is returned unchanged.
- Parameters:
x (real) – A real number.
- Returns:
x rounded toward zero.
- Return type:
integer
Example:
--> (truncate 3.7) 3 --> (truncate -3.7) -3 --> (truncate 7/2) 3 --> (truncate 4) 4
numerator¶
- (numerator q)
Returns the numerator of q, computed as if q were represented as a fraction in lowest terms. If q is an exact integer or bignum, it is returned unchanged (as its own numerator over an implicit denominator of
1).- Parameters:
q (rational or integer) – A rational number or exact integer.
- Returns:
The numerator of q in lowest terms.
- Return type:
integer
Example:
--> (numerator 3/7) 3 --> (numerator 6/4) 3 --> (numerator 5) 5
denominator¶
- (denominator q)
Returns the denominator of q, computed as if q were represented as a fraction in lowest terms. If q is an exact integer, returns
1.- Parameters:
q (rational or integer) – A rational number or exact integer.
- Returns:
The denominator of q in lowest terms.
- Return type:
integer
Example:
--> (denominator 3/7) 7 --> (denominator 6/4) 2 --> (denominator 5) 1
rationalize¶
- (rationalize x y)
Returns the simplest rational number that differs from x by no more than y. A rational p/q is considered simpler than p2/q2 if both
|p| ≤ |p2|and|q| ≤ |q2|when both fractions are in lowest terms. Note that0is the simplest rational of all.The search is limited to denominators up to
10^16. If no suitably simple rational is found within that range, a best-effort rational approximation of x is returned based on the full precision of the floating-point representation.- Parameters:
x (real) – The target value.
y (real) – The maximum permitted difference from x.
- Returns:
The simplest rational number within y of x.
- Return type:
rational
Example:
--> (rationalize 0.1 1/10) 0 --> (rationalize 1/3 1/10) 1/3 --> (rationalize 3.14159 1/100) 22/7 --> (rationalize 0.1 0) 3602879701896397/36028797018963968
square¶
- (square z)
Returns the square of z. Equivalent to
(* z z).- Parameters:
z (number) – A number to square.
- Returns:
The square of z.
- Return type:
number
Example:
--> (square 5) 25 --> (square -3) 9 --> (square 1/3) 1/9 --> (square 2.0) 4.0 --> (square 2+3i) -5+12i
sqrt¶
- (sqrt z)
Returns the principal square root of z. The result will have either a positive real part, or a zero real part and a non-negative imaginary part. If z is an exact non-negative integer whose square root is itself an exact integer, the result is returned as an exact integer. If z is a negative real number, the result is a complex number with zero real part.
- Parameters:
z (number) – A number to take the square root of.
- Returns:
The principal square root of z.
- Return type:
number
Example:
--> (sqrt 4) 2 --> (sqrt 2) 1.4142135623730951 --> (sqrt -1) 0+1.0i --> (sqrt -4) 0+2.0i --> (sqrt 1+2i) 1.272+0.786i
exact-integer-sqrt¶
- (exact-integer-sqrt k)
Returns a list of two exact non-negative integers
(s r)such thatk = s² + r, where s is the largest integer for whichs² ≤ k. k must be a positive exact integer.- Parameters:
k (integer) – A positive exact integer.
- Returns:
A list of two exact integers
(s r)wheresis the integer square root of k andris the remainder.- Return type:
list
Example:
--> (exact-integer-sqrt 14) (3 5) --> (exact-integer-sqrt 16) (4 0) --> (exact-integer-sqrt 2) (1 1)
exact¶
- (exact z)
Returns an exact representation of z. If z is already exact, it is returned unchanged. For inexact real numbers, the exact flag is set on the value. For complex numbers, the exact flag is applied to both the real and imaginary parts individually.
- Parameters:
z (number) – A number to convert to an exact representation.
- Returns:
An exact representation of z.
- Return type:
number
Example:
--> (exact 1) 1 --> (exact 1.5) 1.5 --> (exact 1/3) 1/3
inexact¶
- (inexact z)
Returns an inexact representation of z. If z is already inexact, it is returned unchanged. For exact numbers, the value is promoted to an inexact real via numeric promotion. For complex numbers, the exact flag is cleared on both the real and imaginary parts individually.
- Parameters:
z (number) – A number to convert to an inexact representation.
- Returns:
An inexact representation of z.
- Return type:
number
Example:
--> (inexact 1) 1.0 --> (inexact 1/3) 0.3333333333333333 --> (inexact 1.5) 1.5
infinite?¶
- (infinite? z)
Returns
#tif z is a real infinite value (+inf.0or-inf.0), or a complex number whose real or imaginary part (or both) is infinite. Returns#ffor all other numbers, including exact integers, rationals, and bignums.- Parameters:
z (number) – The number to test.
- Returns:
#tif z is infinite,#fotherwise.- Return type:
boolean
Example:
--> (infinite? +inf.0) #t --> (infinite? -inf.0) #t --> (infinite? 1.0) #f --> (infinite? 42) #f
finite?¶
- (finite? z)
Returns
#tif z is a finite number. Returns#ffor+inf.0,-inf.0, and+nan.0. For complex numbers, returns#tonly if both the real and imaginary parts are finite. Exact integers, rationals, and bignums are always considered finite.- Parameters:
z (number) – The number to test.
- Returns:
#tif z is finite,#fotherwise.- Return type:
boolean
Example:
--> (finite? 42) #t --> (finite? 1.5) #t --> (finite? +inf.0) #f --> (finite? +nan.0) #f
nan?¶
- (nan? z)
Returns
#tif z is+nan.0, or a complex number whose real or imaginary part (or both) is+nan.0. Returns#ffor all other numbers, including exact integers, rationals, and bignums.- Parameters:
z (number) – The number to test.
- Returns:
#tif z is+nan.0,#fotherwise.- Return type:
boolean
Example:
--> (nan? +nan.0) #t --> (nan? 1.0) #f --> (nan? 42) #f
gcd¶
- (gcd n ...)
Returns the greatest common divisor of its arguments. The result is always non-negative. If no arguments are provided, returns
0, which is the identity value for GCD. If a single argument is provided, its absolute value is returned.- Parameters:
n (integer) – Zero or more exact integers.
- Returns:
The greatest common divisor of all arguments, or
0if no arguments are given.- Return type:
integer
Example:
--> (gcd) 0 --> (gcd 12) 12 --> (gcd 12 8) 4 --> (gcd 32 -36) 4 --> (gcd 12 8 6) 2
lcm¶
- (lcm n ...)
Returns the least common multiple of its arguments. The result is always non-negative. If no arguments are provided, returns
1, which is the identity value for LCM. If a single argument is provided, its absolute value is returned.- Parameters:
n (integer) – Zero or more exact integers.
- Returns:
The least common multiple of all arguments, or
1if no arguments are given.- Return type:
integer
Example:
--> (lcm) 1 --> (lcm 6) 6 --> (lcm 4 6) 12 --> (lcm -4 6) 12 --> (lcm 4 6 10) 60