Fibonacci number program
In many beginning computer science courses, an introduction to the concept of recursion often includes a program to calculate and print Fibonacci numbers. In general, however, a recursive algorithm to compute Fibonacci numbers is extremely inefficient when compared to an iterative algorithm. In addition, an iterative algorithm is generally more intuitive and easier to write.
| Table of contents |
|
2 Perl examples 3 Python examples 4 Haskell examples 5 Scheme examples 6 See also |
Mathematical definition:
my ($a, $b) = (0, 1);
for (;;) {
The above algorithm is the classical recursive solution, and is very
inefficient. The algorithm runs in O (F(n)) time.
In Perl, this can easily be solved by having the function cache calculated
values, turning the program into one that runs in linear time:
The solution below uses an iterative algorithm:
This is an optimized algorithm so it runs in linear time. It is a generator that returns a list's next element when called.
This is an optimized algorithm so it runs in linear time. It creates an infinite list, but only the necessary elements are computed due to Haskell being lazy.
The above algorithm runs in O (F(n)) time, since it uses tree recursion and often unnecessarily recalculates values. The algorithm shown below, on the other hand, runs in O (n) time, much faster:
Since the second algorithm proceeds iteratively, each Fibonacci value is calculated at most once, rather than several times as in the first algorithm.
The first algorithm is called recursive, while the second algorithm, not quite iterative, is called tail-end recursive. Tail-end recursion is practically the same as iteration with regard to running time, since the processes are equivalent: indeed, an intelligent compiler can often compile a tail-recursive program into an iterative equivalent.Definiton
f(0) = 1
f(1) = 1
f(n) = f(n-1) + f(n-2)
Perl examples
1
use bigint; print("$a\
");
($a, $b) = ($b, $a+$b);
}
2 - Recursive (inefficient)
sub fib;
sub fib {$_ [0] < 2 ? $_ [0] : fib ($_ [0] - 1) + fib ($_ [0] - 2)}
3 - Efficient
use Memoize;
memoize 'fib';
sub fib;
sub fib {$_ [0] < 2 ? $_ [0] : fib ($_ [0] - 1) + fib ($_ [0] - 2)}
4 - Iterative (efficient)
sub fib {my ($n, $a, $b) = (shift, 0, 1);
($a, $b) = ($b, $a + $b) while $n -- > 0;
$a}
Python examples
1 - Generator (efficient iterative)
def fib():
yield 1
yield 1
a, b = 1, 1
while True:
a, b = b, a+b
yield b
Haskell examples
1 - Infinite list (efficient)
fib = 1 : 1 : zipWith (+) fib (tail fib)
Scheme examples
1 - Inefficient
(define fab
(lambda (x)
(if (< x 2)
x
(+ (fab (- x 1)) (fab (- x 2))))))
2 - Tail-end recursive (efficient)
(define (fab x)
(define (fab-iter x a b)
(if (= x 0)
a
(fab-iter (- x 1) b (+ a b))))
(fab-iter x 0 1))