7

有谁知道如何在 Lisp 中为浮点数指定小数点后的位数?

假设我在 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.... 

谢谢,

卢卡

4

3 回答 3

20

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

Common Lisp 在标准中定义了四种浮点类型:SHORT-FLOAT, SINGLE-FLOAT, DOUBLE-FLOAT, LONG-FLOAT

您可以使用该函数将比率强制为浮点数COERCE(LispWorks 中的示例):

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

或作为LONG-FLOATCLISP 中的

[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
于 2012-08-16T10:21:55.683 回答
3

除了 Rainer 的出色回答之外,我认为您还想查看函数RATIONALIZE

(rationalize (float 1/7))
1/7
于 2012-08-16T17:19:55.070 回答
3

您也可以手动进行除法,在这种情况下您仍然需要比 long long long 更长的值(已知对于某些编译器来说太长了;)像这样:

(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

可能有更有效的方法来计算小数部分,但它们太复杂了(对我来说,对于这个例子来说也是如此)。

于 2012-08-18T08:44:38.320 回答