I have the following code :
(defn series-sum
"Compute a series : (+ 1 1/4 1/7 1/10 1/13 1/16 ...)"
[n]
(->> (iterate (partial + 3) 1)
(map #(/ 1 %))
(take n)
(reduce +)
float
(format "%.2f")
(str)))
It is working just fine, except that it's running time explodes when numbers get big. On my computer (series-sum 2500)
is maybe a second or two, but (series-sum 25000)
and I have to kill my REPL.
I tried moving (take n)
as far as possible, but that is not enough. I feel that I don't understand something about Clojure since I don't see why it would be slower (I would expect (series-sum 25000)
to take roughly 10 times as (series-sum 2500)
).
There is an obvious loop/recur solution to optimize it, but I like the idea of being able to print the steps and to have one step (the (take n)
looking like the docstring).
How can I improve the performance of this code while maintaining debuggability ?
Better yet, can I measure the time of each step to see the one taking time ?
yes, it is relevant to @zerkms's link. You map to rationals, probably should better map to floats:
(defn series-sum
"Compute a series : (+ 1 1/4 1/7 1/10 1/13 1/16 ...)"
[n]
(->> (iterate (partial + 3) 1)
(take n)
(map #(/ 1.0 %))
(reduce +)
(format "%.2f")))
now it works much faster:
user> (time (series-sum 2500000))
"Elapsed time: 686.233199 msecs"
"5,95"
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With