2012-08-16 19 views
5

, Lisp'de bir kayan nokta için ondalık noktadan sonraki rakamların sayısını nasıl belirtebilir? Ben repl bu komutu yazdırırsanızLISP - ondalık basamaktan sonraki basamaklar

ki:

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

alıyorum:

0.142857150000000 

Ama sayı ondalık noktadan sonraki 8 rakamında yuvarlanır, bir görmek gerek sayının döngüsel olup olmadığını ve periyodu hesaplamak için ondalık noktadan sonraki rakam çokluğu. (Aslında Project Euler'in problemini çözmeye çalışıyorum ve 26).

Böyle bir şey almak gerekir:

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

Teşekkür ederim,

Luca

cevap

17

Common Lisp kendi standardında keyfi doğruluk ile yüzen yoktur. SHORT-FLOAT, SINGLE-FLOAT, DOUBLE-FLOAT, LONG-FLOAT:

Common Lisp standart dört yüzer tiplerini tanımlar.

Sen fonksiyonunu COERCE (LispWorks içinde örnek) kullanarak bir şamandıraya bir oran zorlamak olabilir:

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

veya LONG-FLOAT CLISP

yılında

İhtiyacınız uzun şamandıra numaraları ile hesaplamak için bir olarak

Common Lisp için uzantılar. GNU CLISP olmayan bir taşınabilir uzantısına sahiptir ve (ikili) basamak sayısını ayarlayabilirsiniz:

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

Örnek:

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

Teşekkürler, bu gerçekten yardımcı oldu. – Luca

3

, ben kontrol etmek istediğiniz düşünüyorum fonksiyonu RATIONALIZE üzerinden:

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

Ayrıca elle ile bölüm yapabilirsiniz nereye st olur

(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 

Orada kesirli kısmı hesaplamak için daha etkili yollar olabilir, ama bunlar çok karmaşıktır olabilir (: Böyle bir şey; hasta ihtiyaç değerleri artık o uzun uzun uzun (bilinen bazı derleyiciler için çok uzun olması için) benim için ve bu örnek için olurdu).