Last night I did very small superficial comparison, of 3 ways of getting the first fibonnaci number consisting of 1000 digits. This attracted a lot of attention from Rubists, Haskaloonies and Clojurians alike, here I'll share their contributions.
Microbenchmarking sucks, especially on the JVM. HotSpot is doing such a great job of optimizing code, that sometimes you end up getting an incorrect idea of how your code performs. Nevertheless I got, many tips for improving performance, so it seems the Internet Performance Rule of Thumb is: Always benchmark the Fibs!
Team Haskell weren't pleased completing the job in 7 msecs, so they suggested that I recompile the program using -O2. I used GHC v. 6.10:
limit = 10^999 fibs = 0 : 1 : zipWith (+) fibs (tail fibs) main = print . length . takeWhile (< limit) $ fibs
(thanks to: "laulau")
Real time, average of 20: 7 msecs.
Nothing gained, but 7 msecs is blazing.
Ruby had big room for improvement as the very clever Matrix approach didn't yield very satisfying performance. Here's one commentators approach
limit = 10**999 def fib2(a,b) return b,b+a end a,b = fib2(0,1) while b < limit a,b = fib2(a,b) end puts b
(thanks to: Aaron)
Average on 20 runs: 35 msecs.
Huge improvement and honor is restored to the Ruby camp!
Camp Scala was good enough to contribute a solution as well:
object Main {
def main(args: Array[String]) {
def f(a: BigInt, b: BigInt) = (b, b + a)
val max = BigInt(10).pow(999)
var (a, b) = f(0, 1)
while(b < max) {
val temp = f(a, b)
a = temp._1
b = temp._2
}
println("\nb = " + b)
}
}
(thanks to: Rahul G ,*updated*)
Average: 18 ms.
Clojures loops are recursive and side-effect free, but even still it looks a little clunky:
(time (let [limit (.pow (BigInteger/TEN) 999)] (loop [a 0 b 1 i 1] (if (< b limit) (recur b (+ a b) (inc i)) i)))) (thanks to: Duc)
Nevertheless, it averages at: 5 msecs. Hooray! It's a new record!
If nothing else I think its fun to see these challenges approached from different languages, which is also what I like about Project Euler. And I'm certain that this will not be the last time I bring Haskell along for the ride. Last nights post were meant as small reflections on 3 very different languages, so I was a little surprised of the attention that it got - But its positive, I think its great when we all can learn a little from one another.
I'm open for ideas on another arena for comparisons. We could do something crazy like solve Global Warming.. oh wait, I already did that. How about Euler 200 then?