Problem
Each new term in the Fibonacci sequence is generated by adding the previous two terms. By starting with 1 and 2, the first 10 terms will be:
1, 2, 3, 5, 8, 13, 21, 34, 55, 89, ...
Find the sum of all the even-valued terms in the sequence which do not exceed four million.
Solution
The naive approach to this algorithm would be to just implement the recursive Fibonacci function and do what the problem says. We'd end up with something like this:
int fib(int n) { return n < 2 ? n : fib(n-1) + fib(n-2); }
int sum = 0;
for (int n = 0; fib(n) < 4000000; ++n)
if (fib(n) % 2 == 0)
sum += fib(n);
Luckily, 4 million is small enough so that this algorithm runs fairly quickly (about half a second on my machine). If the upper bound was much bigger, we would run into very serious performance issues. The reason is because the implementation of the Fibonacci function shown there runs in exponential time i.e. the time that it takes to calculate fib(n) is proportional to
. In concrete terms, we're talking milliseconds to calculate fib(10), and millions of years to calculate fib(100) (that's not an exaggeration -- it's actually around 5 million years for my computer).
Since we do actually get an answer before the end of the universe, we could just move onto the next problem, but we wouldn't have learned much. It's worthwhile putting in some extra effort now to make our Fibonacci function run faster.
There are many ways to generate Fibonnaci quickly, so I'll only mention a few here.
Iterative
The iterative method simply starts at fib(1) and works its way up to fib(n), remembering the previous two values at each stage:
int fib(int n)
{
if (n < 2)
return n;
int fp = 0, f = 1;
foreach (i; 1..n)
{
swap(fp, f);
f += fp;
}
return fp;
}
As we only have one simple loop with no recursion, this approach obviously runs in time linear in
.
Memoization
Memoization is a common technique for improving the complexity of recursive functions. The concept is simple: once you have calculated a value, store it somewhere and use that value instead of calculating it again. The beauty of memoization is that it allows you to keep your elegant recursive definition.
int fib(int n)
{
static int[] cache = [0, 1];
if (n >= cache.length)
cache ~= fib(n-1) + fib(n-2);
return cache[n];
}
Note that I have been a little cheeky with the memoization part here by simply appending the newly calculated value onto the end of the array, assuming that it will be in the right position. If you think about it though, it always will be in the right position, because fib(n-1) would have been calculated before the append, which means that the array will be
elements long when the append actually happens, which is what we want.
The performance here is linear in
for the first time you calculate a value then constant for subsequent invocations.
Closed-Form Formula
Interestingly, there exists a closed form formula for calculating the nth Fibonacci number. It is:


Let's put it into action:
int fib(int n)
{
double phi = (1.0 + sqrt(5.0)) / 2.0;
double f = (pow(phi, n) - pow(1.0 - phi, n)) / sqrt(5.0);
return cast(int)(f + 0.5);
}
Assuming pow(double, int) is implemented using the exponentiation by squaring algorithm, this will run in logarithmic time.