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