有没有人知道如何在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....
谢谢,
卢卡
答案 0 :(得分:18)
Common Lisp在其标准中没有任意精确的浮点数。
Common Lisp在标准中定义了四种浮点类型:SHORT-FLOAT
,SINGLE-FLOAT
,DOUBLE-FLOAT
,LONG-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
可能有更有效的方法来计算小数部分,但它们太复杂了(对我来说,并且就这个例子而言)。