Common Lisp/Advanced topics/Numbers
Common Lisp has much more support for performing number-crunching tasks than most programming languages. This is achieved by having support for large integers, rational numbers, and complex numbers, as well as many functions to work on them.
Types of numbers
The hierarchy of the number type is as follows:
Fixnums and Bignums
Fixnums are integers which are not too large and can be manipulated very efficiently. Which numbers are considered fixnums is implementation-dependant, but all integers in [-215,215-1] are guaranteed to be such.
Bignums are integers which are not fixnums. Their size is limited by the amount of memory allocated for Lisp, and as such they can be really large. Operations on them are significantly slower than on fixnums. Of course, that doesn't make them less useful.
Ratios represent the ratio of two integers. They have the form numerator/denominator. The function / which performs division always produces ratios when its arguments are integers or ratios. For example
(/ 1 2) will result in 1/2, not 0.5. Other arithmetic operations also work fine with ratios.
Float is short for floating-point number, a datatype used to represent non-integer numbers in most programming languages. There are four kinds of floats in Common Lisp, which provide increasing precision (implementation-dependent). By default, implementations assume short floats, which have limited precision. To input a more precise float, other textual notations must be used, e.g., "1.0d0" for a double-float.
Complex is a datatype for representing complex numbers. The notation for complexes is #C(real imaginary). Real and imaginary parts are both either rational or floating-point. The operations that can be performed on complexes include all arithmetic operations and also many other functions which can be extended to complex numbers (such as exponentiation and logarithm).
The following functions are defined for all kinds of numbers:
- The arithmetical operations +,-,*,/ are quite obvious (note, though, that they can have more than two parameters).
- sin, cos, tan, acos, asin, atan provide trigonometric functions.
- The same, with h at the end (like asinh) provide corresponding hyperbolic functions.
- exp and expt perform exponentiation. exp accepts one parameter and calculates ex, while expt accepts two parameters (base and power).
- sqrt calculates the square root of a number.
- log calculates logarithms. If one parameter is supplied, the natural logarithm is calculated. If there are two parameters, the second parameter is used as the base.
- conjugate returns the complex conjugate of a number. For real numbers the result is the number itself.
- abs returns the absolute value (or magnitude) of a number.
- phase returns the complex argument (angular component) of a number.
- signum returns a number with the same phase as its argument, but with unit magnitude.
The following functions are defined for specific kinds of numbers:
- gcd and lcm calculate greatest common divisor and least common multiple of several integers.
- isqrt returns the greatest integer less than or equal to the exact square root of a given natural number.
- cis calculates eiφ where φ is supplied in radians.
Comparison of numbers
The following functions can be used for comparison of numbers. Each of these functions accepts any number of arguments.
- = returns t if all arguments are numbers of the same value and nil otherwise. Due to imprecise nature of floating-point numbers it is not advised to use = on them.
- /= returns t if all arguments are numbers of different value. Note that
(/= a b c)is not always the same as
(not (= a b c)).
- <, <=, >, >= check if their arguments are in the appropriate monotonous order. These functions can't be applied to complex numbers for obvious reasons.
- max and min return the largest and the least of their arguments, respectively.
Numeric type manipulation
These functions are used to convert numbers from one type to another.
- floor, ceiling, truncate, round take two arguments: number and divisor and return quotient (an integer) and reminder=number-quotient*divisor. The method for choosing the quotient depends on the function. floor chooses the largest integer that is not greater than ratio=number/divisor, ceiling chooses the smaller integer that is larger than ratio, truncate chooses the integer of the same sign as ratio with the largest absolute value that is less than absolute value of ratio, and round chooses an integer that is closest to ratio (if there are two such numbers, an even integer is chosen). Note: these functions return two values (see Multiple values).
- ffloor, fceiling, ftruncate, fround are the same as above but the quotient is converted to the same float type as number.
- (mod a b) returns the second value of (floor a b).
- (rem a b) returns the second value of (truncate a b).
- float converts its first argument (a real) to a float. It may be useful to avoid slow operations with rational numbers (see example 1). The second optional argument may be supplied, which must be float - it will be used as a prototype. The result would be of the same floating-point type as a prototype.
- rational and rationalize convert a real number to rational. When this number is a float rational returns a rational number that is mathematically equivalent to float. rationalize approximates the floating-point number. The former function usually produces ratios with a huge denominator so it's not as useful as you may think.
- numerator and denominator return the corresponding parts of a rational number.
- complex creates a complex number from its real part and imaginary part. Functions realpart and imagpart return real and imaginary part of a number.
Predicate returns a non-nil result if it's true and nil if it is false.
- zerop - the number is zero (there may be several zeros in Lisp - integer zero, real zero, complex zero, there may be negative zeros too).
- plusp, minusp - the real number is positive/negative.
- evenp, oddp - the integer is odd/even.
- integerp - the number is integer (of the type integer - see type tree above).
- floatp - the number is float.
- rationalp - the number is rational.
- realp - the number is real.
- complexp - the number is complex.