2013-05-20 20 views
10

Dies ist ein Lisp-Code, der Tail-Rekursion verwendet.Tail Rekursion in Clojure

Ich übersetze dies in Clojure-Code erwartet die gleiche Tail-Rekursion-Optimierung.

(defn fact [f n] 
    (if (= n 1) 
     f 
     (fact (* f n) (dec n)))) 

Allerdings habe ich diesen Integer-Überlauf (nicht über Stack) auch bei kleiner Zahl wie (fact 1 30).

ArithmeticException integer overflow clojure.lang.Numbers.throwIntOverflow (Numbers.java:1374) 

Ich habe versucht, mit recur, bekam aber den gleichen Fehler.

(defn factorial [f n] 
    (if (= n 1) 
     f 
     (recur (* f n) (dec n)))) 

Was ist falsch mit dem Clojure-Code?

+7

Auch lohnt es sich, darauf hingewiesen, dass Clojure, aufgrund von Einschränkungen der JVM, nicht automatisch Endrekursion Optimierung unterstützt. 'recur 'ist in der Tat der Weg für eine rekursive Redewendung in diesem Fall. – JohnJ

+0

Wo finde ich in der clojure docs Beispiele für die Verwendung von reacon ohne Schleife? So wie du es hier benutzt hast. – SultanLegend

Antwort

18

Nichts, benutzen Sie einfach BigInt s:

(factorial 1N 30N) ;=> 265252859812191058636308480000000N 

Die Argumente klein sein kann, aber das Ergebnis ist nicht!

Beachten Sie, dass Versionen der arithmetischen Operatoren abgehakt sind ebenfalls verfügbar, die mit beliebiger Genauigkeit unterstützen:

(reduce *' (range 1 31)) ;=> 265252859812191058636308480000000N 
Verwandte Themen