2012-08-16 19 views
5

¿Alguien sabe cómo especificar el número de dígitos después del punto decimal para un flotador en Lisp?LISP - dígitos después del punto decimal

Di si imprimo este comando en el REPL:

CL-USER 3 > (format t "~,15f" (float (/ 1 7))) 

me sale:

0.142857150000000 

Sin embargo, el número se redondea al octavo dígitos después del punto decimal, necesito ver una muchos dígitos después del punto decimal para ver si el número es cíclico y para calcular el período. (En realidad estoy empezando a tratar de resolver el problema del Proyecto Euler 26).

que necesita para obtener algo como esto:

CL-USER 3 > (format t "~,15f" (float (/ 1 7))) 
0.142857142857142857142857142857142857.... 

Gracias,

Luca

Respuesta

17

Common Lisp no tiene flotadores con exactitud arbitraria en su estándar.

Common Lisp define cuatro tipos de flotador en el estándar: SHORT-FLOAT, SINGLE-FLOAT, DOUBLE-FLOAT, LONG-FLOAT.

Usted puede coaccionar a una relación a un flotador mediante la función COERCE (ejemplo en la LispWorks):

CL-USER 1 > (coerce (/ 1 7) 'double-float) 
0.14285714285714285D0 

o como LONG-FLOAT en CLISP

Para calcular con números flotantes más largos que necesita extensiones de Common Lisp. GNU CLISP tiene una extensión no portátil y se puede establecer el número de dígitos (binarios):

(SETF (EXT:LONG-FLOAT-DIGITS) n)

Ejemplo:

[3]> (SETF (EXT:LONG-FLOAT-DIGITS) 1000)  
1000 
[4]> (coerce (/ 1 7) 'long-float) 
0.142857142857142857142857142857142857142857142857142857 
142857142857142857142857142857142857142857142857142857 
142857142857142857142857142857142857142857142857142857 
142857142857142857142857142857142857142857142857142857 
142857142857142857142857142857142857142857142857142857 
142857142857142857142857142857142857143L0 
+0

Gracias, que fue muy útil. – Luca

3

Además de una excelente respuesta de Rainer, creo que desea comprobar la función RATIONALIZE:

(rationalize (float 1/7)) 
1/7 
3

también se puede hacer una división a mano, donde se haría st Los valores necesitan enfermos ya continuación, largo, largo tiempo (que se sabe que es demasiado largo para algunos compiladores;) Algo como esto:

(defun divide (a b &key (precision 8)) 
    (let ((fractional 0)) 
    (multiple-value-bind (whole reminder) 
     (floor a b) 
     (unless (zerop reminder) 
     (dotimes (i precision) 
      (setf reminder (* reminder 10)) 
      (multiple-value-bind (quot rem) 
       (floor reminder b) 
      (setf fractional (+ (* fractional 10) quot)) 
      (when (zerop rem) (return)) 
      (setf reminder rem)))) 
     (values whole fractional)))) 

(multiple-value-call #'format t "~d.~d~&" (divide 1 7)) 
(multiple-value-call #'format t "~d.~d~&" (divide 1 7 :precision 54)) 

;; 0.14285714 
;; 0.142857142857142857142857142857142857142857142857142857 

Puede haber formas más eficientes para el cálculo de la parte fraccionaria, pero son demasiado complejos (para mí, y sería para este ejemplo).

Cuestiones relacionadas