7

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.... 

ありがとうございました、

ルカ

4

3 に答える 3

20

Common Lisp の標準には、任意の正確さを持つ float はありません。

Common Lisp は、標準で 4 つの float 型を定義しています: SHORT-FLOATSINGLE-FLOAT、。DOUBLE-FLOATLONG-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

レイナーの優れた回答に加えて、関数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 に答える