Nyquist/XLISP only knows two types of numers:
In Nyquist/XLISP, there are no ratios or complex numbers. Even if the
math functions on this page are modelled after
(setq *most-positive-fixnum* 2147483647) (setq *most-negative-fixnum* -2147483648)
Note: these are the limits for
(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")))
The '
(defun print-float (item)
(if (not (floatp item))
item
(let ((string (format nil "~a" item)))
(if (not (string-search "." string))
(strcat string ".0")
string))))
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
The cl:round, cl:truncate, cl:ceiling and cl:floor functions divide a number by a divisor, returning a quotient and a remainder:
The 'quotient' always represents a mathematical integer.
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
The
(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
The '
| 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 '
(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)
The '
| 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 '
The '
| 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 '
The '
| 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
The cl:mod and cl:rem
function are generalizations of the modulus and remainder functions.
(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 '
(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 '
The '
(defun cl:exp (x) (exp (float x)))
The '
The '
(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,
The '
The '
(defun cl:log (number &optional base)
(if base
(if (zerop base)
0.0
(/ (log (float number)) (log (float base))))
(log (float number))))
The '
The '
(defun cl:sqrt (x) (sqrt (float x)))