murtaza52
murtaza52

Reputation: 47441

recursive call resulting into overflow

I am trying to solve the project euler 2nd question. Why is the below code resulting into stack overflow ? I am using recur so it should not be storing all the recursive calls on the stack.

(defn sum
  [[a b]]
  [b (+ a b)])

(defn fib-r
  ([n] (fib-r n 0 [0 1]))
  ([n s [a b]]
     (if (= n 0)
       s
       (let [[c d] (sum [a b])
             e (if (even? c) c 0)
             f (+ s e)]
         (recur (dec n) f [c d])))))

(fib-r 4000000)

Upvotes: 2

Views: 96

Answers (2)

Paweł Łoziński
Paweł Łoziński

Reputation: 1094

This was a big change made in Clojure 1.3 (see http://dev.clojure.org/display/doc/Enhanced+Primitive+Support for details) auto-promotion of primitive types does not happen automatically.

You don't have to use BigInts everywhere as Arthur Ulfeldt suggests, you can instead use auto-promoting plus operation +':

(defn sum [[a b]] [b (+' a b)])

This will do.

In regards to the 4 million case - yes this computation is large. You can modify your fib-r function like this:

(defn fib-r
  ([n] (fib-r n 0 [0 1]))
  ([n s [a b]]
     (if (and (< 0 n) (zero? (mod n 100000)))
       (println n))
     (if (= n 0) s
       (let [[c d] (sum [a b])
             e (if (even? c) c 0)
             f (+ s e)]
         (recur (dec n) f [c d])))))

to see how fast this is going.

Upvotes: 1

Arthur Ulfeldt
Arthur Ulfeldt

Reputation: 91534

your getting an integer overflow (rather than a stack overflow) If you use BigInts (BigInt literals end with N) then Clojure will happily compute the correct result:

(defn fib-r                                                                                          
  ([n] (fib-r n 0N [0N 1N]))                                                                     
  ([n s [a b]]                                                                                     
     (if (= n 0N)                                                                            
       s                                                                            
       (let [[c d] (sum [a b])                                               
             e (if (even? c) c 0N)                               
             f (+ s e)]                             
         (recur (dec n) f [c d])))))
#'autotestbed.core/fib-r                                                                                               
autotestbed.core> (fib-r 40000)
1158997879999727672946417013062336891791160667328280503727448.... big number

Upvotes: 6

Related Questions