Computing the Fibonacci Numbers
This page contains various implementations of ways to
compute the Fibonacci number. The first make use of the
well-known defining equation
fibonacci(n+2) = fibonacci(n)+fibonacci(n+1)
and is quite slow as it recursively calls itself excessively
(and causes therefore a delay in loading this page).
The second function has several small values precomputed and
uses the equations
fibonacci(2n) = 2*fibonacci(n)*fibonacci(n+1)-fibonacci(n)*fibonacci(n);
fibonacci(2n+1) = fibonacci(n)*fibonacci(n)+fibonacci(n+1)*fibonacci(n+1);
fibonacci(2n+2) = 2*fibonacci(n)*fibonacci(n+1)+fibonacci(n+1)*fibonacci(n+1).
These equations permit to compute a Fibonacci number by calling the function
at values of half the size. This brings down the exponential complexity
of the first implementation to a linear number of calls of subroutines
(measured in input n). So, for fibonacci(n), one would need
fibonacci(m) and fibonacci(m+1) where m is the downrounded value of n/2.
One can bring this further down by computing fibonacci(n) and fibonacci(n+1)
both simulatneously from fibonacci(m) and fibonacci(m+1). As functions
have only one return value, an adjustment with less function calls could
be made by storing fibonacci(m+1) in the global variable nextfib when
fibonacci(m) is called. The resulting implementation needs only a logarithmic
number of recursive calls when computing the fibonacci number at n.
var nextfib;
function fastfibonacci(y)
{ var z; var a; var b;
switch(y)
{ case 0: nextfib = 1; return(0); break;
case 1: nextfib = 1; return(1); break;
case 2: nextfib = 2; return(1); break;
case 3: nextfib = 3; return(2); break;
case 4: nextfib = 5; return(3); break;
case 5: nextfib = 8; return(5); break;
default: z = Math.floor(y*0.5+0.1);
a = fastfibonacci(z); b = nextfib;
if (y%2 == 0) { nextfib = a*a+b*b; return(2*a*b-a*a); }
else { nextfib = 2*a*b+b*b; return(a*a+b*b); } break; } }
Below are sample outputs of all three functions. As Fibonacci numbers
grow fast in size, it becomes impossible to display all digits for large n.
The values beyond 78 have rounding errors and are therefore not shown.
Remarks on the Complexity
Note that the complexity analysis given here counts additions and
multiplications as unit time operations.
This might be a bit rough, given the size of the numbers involved.
For a more realistic analysis, one could also count the time
usage for addition as O(n) and multiplication as O(n log n log log(n)),
see the corresponding
Wikipedia page.
Then the corresponding complexities would be exponential,
O(n (log(n))^2*O(log log(n))) and O(n log(n) log log(n)), for the three
algorithms given here. Also the direct formula would due to the square
roots and powers not be much better than the fastest algorithm above.