LISP - 小数点后的数字

时间:2012-08-16 09:56:13

标签: lisp common-lisp number-formatting

有没有人知道如何在Lisp中为float指定小数点后面的数字?

如果我在REPL打印此命令:

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

我明白了:

0.142857150000000 

但是数字在小数点后的第8位被舍入,我需要在小数点后面看到很多位数,以便查看数字是否是循环的并计算周期。 (实际上,我开始尝试解决Project Euler的问题26)。

我需要得到这样的东西:

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

谢谢,

卢卡

3 个答案:

答案 0 :(得分:18)

Common Lisp在其标准中没有任意精确的浮点数。

Common Lisp在标准中定义了四种浮点类型:SHORT-FLOATSINGLE-FLOATDOUBLE-FLOATLONG-FLOAT

你可以使用函数COERCE(在LispWorks中的例子)强制浮动比率:

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

或CLISP中的LONG-FLOAT

[1]> (coerce (/ 1 7) 'long-float)
0.14285714285714285714L0

要计算较长的浮点数,您需要扩展Common Lisp。 GNU CLISP具有非可移植扩展,可以设置(二进制)数字的数量:

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

示例:

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

答案 1 :(得分:3)

除了Rainer的优秀答案, 我想你想查看函数RATIONALIZE

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

答案 2 :(得分:3)

你也可以手工分割,你仍然需要更长的时间长的长度(对于某些编译器来说已知太久了);这样的事情:

(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

可能有更有效的方法来计算小数部分,但它们太复杂了(对我来说,并且就这个例子而言)。