2.2.4.1.1. Reales a Enteros: Truncamiento o Redondeo

Como explicábamos en un capítulo anterior, la funciónFIX convierte los números reales a enteros a base de un simpletruncamiento de la parte no entera. Este procedimiento no es satisfactorio enmuchos casos donde se requiere un grado mayor de precisión. Asíobtendremos el mismo resultado para (fix 6.1) que para (fix 6.9), en amboscasos simplemente 6.

Una conversión más precisa se obtiene utilizando para laconversión la función RTOS que además de convertir elnúmero real a cadena de caracteres, es capaz, cuando se especifica cero comonúmero de decimales, de realizar unna aproximación al enteromás cercano. Así (rtos 6.1 2 0) devuelve 6 mientras que (rtos 6.92 0) devuelve 7.

Podemos definir una función ROUND de redondeo como sigue:

(defun round (num)
(read (rtos num 2 0))
) ;_ fin de defun

Hasta ahí bien, pero para 6.5 esta función realizaríala aproximación al entero mayor, que en este caso sería 7. Con loque no se cumpliría la definición propuesta para la norma deCommon LISP, donde se especifica que:

si el número se encuentra exactamente a mitad de caminoentre dos enteros (es decir, en la forma entero + 0.5), entonces se redondea alentero par más próximo (divisible por 2). (Steele, CLTL2)

Para cumplir esta especificación deberemos desarrollar unafunción más compleja, que llamaremos CL-ROUND, siguiendo la normacitada.

Esta función requerirá un predicado tambén norma deCommon LISP, pero ausente aún de AutoLISP-Visual LISP. El predicadoEVENP que comprueba si un número entero es par.

(defun evenp (num)
(zerop (rem num 2))
) ;_ fin de defun

La nueva función cl-round recibe el número del cual comprueba:

  • si una vez redondeado el resultado NO es par (not (evenp (setq tmp (rndnum))))
  • si la parte decimal (valor absoluto) es igual a 0.5 (=(abs (rem num 1))0.5)

En caso de que ambas condiciones sean ciertas:

  • si el número es negativo, se le suma 1
  • si el número es positivo se le resta 1
(defun cl-round (num / tmp)
(if
(and
(not (evenp (setq tmp (rnd num))))
(= (abs (rem num 1)) 0.5)
)
(if (minusp tmp)(setq tmp (1+ tmp))(setq tmp (1- tmp)))
) ;_ fin de if
tmp
) ;_ fin de defun