Nyquist / XLISP 2.0  -  Contents | Tutorials | Examples | Reference

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 an integer division:

(cl:truncate 3.0 2.0)              => 1  ; Common Lisp
(/ (truncate 3.0) (truncate 2.0))  => 1  ; Nyquist/XLISP
(/ 3 2)                            => 1  ; integer division

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


Nyquist / XLISP 2.0  -  Contents | Tutorials | Examples | Reference