Nyquist / XLISP 2.0 -
Contents |
Tutorials |
Examples |
Reference
Math
- Number Types
- Integer Limits
- Rounding and Truncation
- Remainder and Modulus
- Power and Roots
Number Types
Nyquist/XLISP only knows two types of numers:
- fixnum - integer numbers
- flonum - floating-point numbers
In Nyquist/XLISP, there are no ratios or complex numbers. Even if the
math functions on this page are modelled after Common Lisp, no
attempt is made to emulate these numbers.
Integer Limits
(setq *most-positive-fixnum* 2147483647)
(setq *most-negative-fixnum* -2147483648)
Note: these are the limits for 32-bit machines.
(defun fixnum-bits ()
(dolist (bits '(15 31 63) nil)
(let ((fixnum (round (expt 2.0 bits))))
(and (plusp (1- fixnum))
(minusp fixnum)
(return (1+ bits))))))
(defun fixnum-limits ()
(if (dolist (bits '(15 31 63) nil)
(let* ((negative (round (expt 2.0 bits)))
(positive (1- negative)))
(when (and (plusp positive)
(minusp negative))
(setq most-positive-fixnum positive
most-negative-fixnum negative)
(return t))))
most-positive-fixnum
(error "fixnum limit not found")))
Back to top
print-float
The 'print-float' function prints
floating-point numbers ending in '.0' as
floating-point numbers and not as integers:
(defun print-float (item)
(if (not (floatp item))
item
(let ((string (format nil "~a" item)))
(if (not (string-search "." string))
(strcat string ".0")
string))))
Back to top
divide-float
An easy way to force a sequence of integers to be divided as floating
point numbers is to insert the number 1.0 after the first argument in the
list of arguments to the divider function or to explicitely convert the
first argument into a floating point number by using the XLISP float function:
(defun divide-float (&rest args)
(if (null args)
(error "too few arguments")
(apply #'/ (cons (float (first args)) (rest args)))))
See apply, cons,
defun, error,
first, float,
if, null,
rest,
&rest.
Examples:
(divide-float 1) => 1.0
(divide-float 1 2) => 0.5
Back to top
Rounding and Truncation
The cl:round,
cl:truncate,
cl:ceiling and
cl:floor functions divide a number by a divisor,
returning a quotient and a remainder:
(cl:round |
number [divisor]) |
⇒ |
quotient, remainder |
(cl:truncate |
number [divisor]) |
⇒ |
quotient, remainder |
(cl:ceiling |
number [divisor]) |
⇒ |
quotient, remainder |
(cl:floor |
number [divisor]) |
⇒ |
quotient, remainder |
quotient * divisor + remainder = number
The 'quotient' always represents a mathematical integer. The
'remainder' is an integer if both 'number' and 'divisor' arguments
are integers, and a floating-point number if either the
'number' or the 'divisor' or both are floating-point
numbers.
With Nyquist/XLISP, the 'quotient' is always directly returned by the
function, while a list:
(quotient remainder)
is stored in the Nyquist/XLISP
*rslt* variable and the
cl:*multiple-values* is
set to T to signal that
Multiple Values are returned.
Examples:
(cl:round 3.5) => 4 ; *rslt* = ( 4 -0.5)
(cl:truncate 3.5) => 3 ; *rslt* = ( 3 0.5)
(cl:ceiling 3.5) => 4 ; *rslt* = ( 4 -0.5)
(cl:floor 3.5) => 3 ; *rslt* = ( 3 0.5)
(cl:round -3.5) => -4 ; *rslt* = (-4 0.5)
(cl:truncate -3.5) => -3 ; *rslt* = (-3 -0.5)
(cl:ceiling -3.5) => -3 ; *rslt* = (-3 -0.5)
(cl:floor -3.5) => -4 ; *rslt* = (-4 0.5)
Force integer division:
(cl:truncate 3.0 2.0) => 1
(/ (truncate 3.0) (truncate 2.0)) => 1
(/ 3 4) => 1
Implementation Notes
(defun name (number &optional (divisor (if (integerp number) 1 1.0)))
... )
The integerp test in the
parameter list signals an error if the 'number' argument is not a number,
also the /
[division] function signals errors if the 'divisor' argument is zero
or not a number, so we do not explicitely need to test the arguments.
The cl:ceiling and cl:floor functions test if 'number' is an
integer multiple of 'divisor' by comparing the results of an integer
division and a floating-point division:
(let ((i-quotient (/ (truncate number) (truncate divisor)))
(f-quotient (/ (float number) divisor)))
(if (= i-quotient f-quotient)
...
I'm not sure if this really catches all cases [e.g.
regarding floating point precision], but have found no problems so
far.
Back to top
cl:round
The 'cl:round' function truncates towards the next
integer:
- (cl:round number [divisor])
- number - an integer or floating-point number
divisor - an integer or floating-point number, except zero
returns |
- |
the result of runding the result of number divided by divisor |
|
- |
the remainder of the round operation |
(defun cl:round (number &optional (divisor
(if (integerp number) 1 1.0)
divisor-p))
(let* ((x (/ (float number) divisor))
(quotient (cond ((and (not divisor-p) (integerp number)) number)
((= number divisor) 1)
((plusp x) (truncate (+ x 0.5)))
((= (- x 0.5) (truncate (- x 0.5)))
(if (minusp x)
(1- (truncate x))
(truncate x)))
(t (truncate (- x 0.5))))))
(setq *rslt* (list quotient (- number (* quotient divisor)))
cl:*multiple-values* t)
quotient))
The 'cl:round' function computes a quotient that has been rounded to the
nearest mathematical integer. If the mathematical quotient is
exactly halfway between two integers, [that is, it has the form
'integer+1/2'], then the quotient has been rounded to the even
[divisible by two] integer. See
Rounding and Truncation
above for more details.
(round 3.5) => 4
(round -3.5) => -3
(cl:round 3.5) => 4 ; *rslt* = ( 4 -0.5)
(cl:round -3.5) => -4 ; *rslt* = (-4 0.5)
Back to top
cl:truncate
The 'cl:truncate' function truncates towards zero:
- (cl:truncate number [divisor])
- number - an integer or floating-point number
divisor - an integer or floating-point number, except zero
returns |
- |
the result of truncating the result of number divided by divisor |
|
- |
the remainder of the truncate operation |
(defun cl:truncate (number &optional (divisor (if (integerp number) 1 1.0)))
(let ((quotient (truncate (/ (float number) divisor))))
(setq *rslt* (list quotient (- number (* quotient divisor)))
cl:*multiple-values* t)
quotient))
The 'cl:truncate' function computes a quotient that has been
truncated towards zero. That is, the quotient represents the mathematical
integer of the same sign as the mathematical quotient, and that has the
greatest integral magnitude not greater than that of the mathematical
quotient. See
Rounding and Truncation
above for more details.
Back to top
cl:ceiling
The 'cl:ceiling' function truncates towards positive
infinity:
- (cl:ceiling number [divisor])
- number - an integer or floating-point number
divisor - an integer or floating-point number, except zero
returns |
- |
the result of truncating the result of number divided by divisor |
|
- |
the remainder of the truncate operation |
(defun cl:ceiling (number &optional (divisor
(if (integerp number) 1 1.0)
divisor-p))
(let ((quotient
(cond ((and (not divisor-p) (integerp number)) number)
((= number divisor) 1)
(t (let ((i-quotient (/ (truncate number) (truncate divisor)))
(f-quotient (/ (float number) divisor)))
(if (or (= i-quotient f-quotient) ; integer result
(not (plusp f-quotient)))
(truncate f-quotient)
(1+ (truncate f-quotient))))))))
(setq *rslt* (list quotient (- number (* quotient divisor)))
cl:*multiple-values* t)
quotient))
The 'cl:ceiling' function computes a quotient that has been
truncated toward positive infinity. That is, the quotient represents the
smallest mathematical integer that is not smaller than the mathematical
result. See
Rounding and Truncation
above for more details.
Back to top
cl:floor
The 'cl:floor' function truncates towards negative infinity:
- (cl:floor number [divisor])
- number - an integer or floating-point number
divisor - an integer or floating-point number, except zero
returns |
- |
the result of truncating the result of number divided by divisor |
|
- |
the remainder of the truncate operation |
(defun cl:floor (number &optional (divisor
(if (integerp number) 1 1.0)
divisor-p))
(let ((quotient
(cond ((and (not divisor-p) (integerp number)) number)
((= number divisor) 1)
(t (let ((i-quotient (/ (truncate number) (truncate divisor)))
(f-quotient (/ (float number) divisor)))
(if (or (= i-quotient f-quotient) ; integer result
(not (minusp f-quotient)))
(truncate f-quotient)
(1- (truncate f-quotient))))))))
(setq *rslt* (list quotient (- number (* quotient divisor)))
cl:*multiple-values* t)
quotient))
The 'cl:floor' function computes a quotient that has been
truncated toward negative infinity. That is, the quotient represents the
largest mathematical integer that is not larger than the mathematical
quotient. See
Rounding and Truncation
above for more details.
Back to top
Remainder and Modulus
The cl:mod and cl:rem
function are generalizations of the modulus and remainder functions.
The cl:mod function performs the
cl:floor operation on its arguments and returns the
remainder of the cl:floor operation.
The cl:rem function performs the
cl:truncate operation on its arguments and returns
the remainder of the cl:truncate operation.
The cl:mod and
cl:rem functions are the modulus and remainder
functions when the 'number' and 'divisor' arguments both are integers.
Back to top
cl:rem
- (cl:rem number divisor)
- number - an integer or floating-point number
divisor - an integer or floating-point number
returns - the remainder of a cl:truncate operation
(defun cl:rem (number divisor)
(if (= (abs number) (abs divisor))
(if (and (integerp number) (integerp divisor)) 0 0.0)
(let ((quotient (truncate (/ (float number) divisor))))
(- number (* quotient divisor)))))
The 'cl:rem' function performs the
cl:truncate operation on its arguments and returns
the remainder of the cl:truncate operation.
The result is either zero or an integer or
floating-point number with the same sign as the 'number'
argument. If both arguments are integer numbers, the
'cl:rem' function is equal to the mathematical remainder
function.
Back to top
cl:mod
- (cl:mod number divisor)
- number - an integer or floating-point number
divisor - an integer or floating-point number
returns - the remainder of a cl:floor operation
(defun cl:mod (number divisor)
(if (= (abs number) (abs divisor))
(if (and (integerp number) (integerp divisor)) 0 0.0)
(let* ((i-quotient (/ (truncate number) (truncate divisor)))
(f-quotient (/ (float number) divisor))
(quotient (if (or (= i-quotient f-quotient) ; integer result
(not (minusp f-quotient)))
(truncate f-quotient)
(1- (truncate f-quotient)))))
(- number (* quotient divisor)))))
The 'cl:mod' function performs the
cl:floor operation on its arguments and returns the
remainder of the cl:floor operation. The
result is either zero or an integer or floating-point
number with the same sign as the 'divisor' argument. If both
arguments are integer numbers, the 'cl:rem' function is equal
to the mathematical modulus function.
Back to top
cl:exp
The 'cl:exp' function does the same as the Nyquist/XLISP
exp function, but it also accepts
integer numbers as argument:
- (cl:exp power)
- power - an integer or floating-point number
returns - the result of 'e' [2.7128] to the power of power
(defun cl:exp (x)
(exp (float x)))
The 'cl:exp' function computes 'e' [2.7128]
raised to the specified 'power'. The result is always a
floating-point number.
Back to top
cl:expt
The 'cl:expt' function computes the result of 'x' to the
power of 'y':
- (cl:expt base power)
- base - the base
power - the exponent
returns - the result of base to the power of power
(defun cl:expt (x y)
(let ((power (expt (float x) y)))
(if (and (integerp x) (integerp y))
(round power)
power)))
See and,
defun,
expt,
float,
if ,
integerp,
let,
power,
round.
The 'cl:expt' function accepts integer and floating point
numbers as arguments. If both arguments are integer numbers,
the result will be an integer number, if one or both arguments
are floating-point numbers, the result will be a
floating-point number. In contrast to the
Nyquist/XLISP expt function, the
'cl:expt' function specifies exactly two arguments.
Back to top
cl:log
The 'cl:log' function does the same as the Nyquist/XLISP
log function, but also accepts
integer numbers and has an optional 'base' argument:
- (cl:log number [base])
- number - an integer or floating-point number
base - an integer or floating-point number
returns - the the logarithm of number in base base
(defun cl:log (number &optional base)
(if base
(if (zerop base)
0.0
(/ (log (float number)) (log (float base))))
(log (float number))))
The 'cl:log' function returns the logarithm of 'number' in
base 'base'. If 'base' is not supplied its value is
'e', the base of the natural logarithms. If the 'base'
argument is zero, then 'cl:log' returns zero. The result is
always a floating-point number.
Back to top
cl:sqrt
The 'cl:sqrt' function does the same as the Nyquist/XLISP
sqrt function, but it also accepts
integer numbers as argument:
- (cl:sqrt number)
- number - an integer or floating-point number
returns - the square root of number
(defun cl:sqrt (x)
(sqrt (float x)))
The result is always a floating-point
number.
Back to top
Nyquist / XLISP 2.0 -
Contents |
Tutorials |
Examples |
Reference