2

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)
1
  • You are recursing 4000000 times (i.e. computing the 4 million-th Fibonacci number), the question only asks for Fibonacci numbers under 4000000. Commented Jun 21, 2012 at 1:57

2 Answers 2

6

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
Sign up to request clarification or add additional context in comments.

2 Comments

I just tried with 4 million, and the repl just hang. Is it because the computation is lo large ?
I timed it and it took 7.28 min on my desktop
1

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.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.