2015-11-09 17 views
5

Ben clojure öğreniyorum ve clojure-koan alıştırmalarından geçiyorum. Egzersizlerden biri implementing a factorial function. Etrafa oynarken fark ettim: Ancak 402387260077093773...Clojure Koan Faktöriyel Fonksiyon Uygulamaları

ben çalıştığınızda tembel aşağıdadır:

REPL içinde (factorial-1 1000N) çağrılması
(defn factorial-1 [n] 
    (loop [n n f 1] 
     (if (= n 1) 
      f 
      (recur (dec n) (* f n))))) 

bir numara verir:

Benim özyinelemeli uygulama büyük sayılar için çalışmak gibi dizisi yaklaşım: Çoğaltma içinde (factorial-2 1000N) Arama

(defn factorial-2 [n] 
    (reduce * 1 (range 1 (inc n)))) 

bir hata verir:

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

Görünüşte tembel sekans yaklaşımı neden tamsayı taşması hatasıyla sonuçlanır?

cevap

4

Veya sadece *' işlevini kullanabilirsiniz. Işlevi, isteğe bağlı kesinliği desteklemektedir. Sayı Long aralığındaysa, Long dönecektir. Aralık Uzun menzili aşarsa, BigInt dönecektir.

+0

İlginç. [* '] (Https://clojuredocs.org/clojure.core/*') işlevini bilmiyordum. Bu işlevin, clojure.core' ad alanında, bunun daha aptalca bir klojür olarak kabul edildiğini varsayalım. – indraniel

8

1000N geçmesine rağmen çarpımlarınızda aslında hiçbir büyük deseni kullanmıyorsunuz, çünkü bu numarayı yalnızca hesaplamanız için son değerini belirlemek için kullanıyorsunuz. Çoğaltmaları 1'da başlatın ve 1, daha sonra 2 ile çarpın, vb. Eğer bir bigint kullanmak factorial-2 sizin tanımı değiştirirseniz, beklenen davranışı elde:

(defn factorial-2 [n] 
    (reduce * 1N (range 1 (inc n)))) 
+0

Ek bilgi için teşekkürler! 'Azaltmak' için başlangıç ​​değerinin türünü değiştirdiğini fark etmemiştim. – indraniel