Quantcast
Viewing all articles
Browse latest Browse all 15

Computing Fibonacci Numbers

Fibonacci series is a number sequence of 0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 44, … It can be expressed by the formula below,

Image may be NSFW.
Clik here to view.
1

Fibonacci series grows almost as fast as the power of 2. Fn ~= 2^(0.694n).

Computation of Fibonacci Numbers
The naive approach to compute Fibonacci numbers is to recursion according to the formula of Fabonacci numbers. A C implementation is given below,

/*

a naive approach of computing fibonacci series, the computation time also satisfy fabonacci series, since

fabonacci series grows almost as fast as power of 2, the computation is expoential time

*/

#include <stdio.h>

#include <stdlib.h>

 

unsigned long fibo(int n) {

    if (n == 0) {

       return 0;

    } else if (n == 1) {

       return 1;

    } else {

       return fibo(n-1) + fibo(n-2);

    }

}

 

int main(int argc, char **argv) {

    int n;

    unsigned long res;

    struct timeval stTime, edTime;

    n = atoi(argv[1]);

    gettimeofday(&stTime, NULL);

    res = fibo(n);

    gettimeofday(&edTime, NULL);

    printf("%lu, time takes (%u:%u)\n", res, (unsigned int)(edTime.tv_sec - stTime.tv_sec), (unsigned int)(edTime.tv_usec - stTime.tv_usec));

}

Suppose the time takes to compute fibo(n-1) and fibo(n-2) are O(n-1) and O(n-2) respectively, then the time complexity of computing fibo(n) is O(n) = O(n-1) + O(n-2). The time complexity itself follows the Fibonacci series. Since we know Fn~= 2^(0.694n), then O(n) ~=2^(0.694n). The computation is exponential. And since O(n)~=(2^0.694)^n ~=1.62^n, compute the Fn+1 takes around 1.6 times longer than computing Fn.

Compile the code using the command,

gcc -o fibo fibo.c

Below is a sample run of the program,

Image may be NSFW.
Clik here to view.

Figure 1. Execution of Recursive Version Program

It is not easy to observe that a Fibonacci number depends on its two previous numbers. The computation above computes some small Fibonacci numbers for many times. We can use an array to remember the previous computation. A C implementation is shown as below,

/*

use dynamic programming to remember previous computation results

this computation runs in linear time

*/

#include <stdio.h>

#include <stdlib.h>

#include <string.h>

 

int main(int argc, char **argv) {

    int n;

    int i;

    struct timeval stTime, edTime;

    unsigned long* fibo;

    n = atoi(argv[1]);

    fibo = (unsigned long*) malloc((n+1)*sizeof(unsigned long));

    memset(fibo, 0x00, sizeof(unsigned long)*n);

    fibo[1] = 1;

    gettimeofday(&stTime, NULL);

    for (i = 2; i <= n; ++i) {

        fibo[i] = fibo[i-1] + fibo[i-2];

    }

    gettimeofday(&edTime, NULL);

    printf("%lu, time takes (%u:%u)\n", fibo[n], (unsigned int)(edTime.tv_sec - stTime.tv_sec), (unsigned int)(edTime.tv_usec - stTime.tv_usec));

}

Compile the code using the command below,

gcc -o fibo1 fibo1.c

A sample run is as below,

Image may be NSFW.
Clik here to view.

Figure 2. Execution of Dynamic Programming Version

It is not difficult to tell the code above runs in linear time. However, the code takes a lot of memory space and if we’re to compute a Fibonacci number Fn for a very large n, then we may run out of memory space.
To compute Fn, we only need values for Fn-1 and Fn-2, this leads to the code below,

/*

use dynamic programming to remember previous computation results

this computation runs in linear time

*/

#include <stdio.h>

#include <stdlib.h>

#include <string.h>

 

int main(int argc, char **argv) {

    int n;

    int i;

    struct timeval stTime, edTime;

    unsigned long fibo[2];

    n = atoi(argv[1]);

    fibo[0] = 0;

    fibo[1] = 1;

    gettimeofday(&stTime, NULL);

    for (i = 2; i <= n; ++i) {

        fibo[i%2] = fibo[0] + fibo[1];

    }

    gettimeofday(&edTime, NULL);

    if (n&0x01) {

        printf("%lu, time takes (%u:%u)\n", fibo[1], (unsigned int)(edTime.tv_sec - stTime.tv_sec), (unsigned int)(edTime.tv_usec - stTime.tv_usec));

    } else {

        printf("%lu, time takes (%u:%u)\n", fibo[0], (unsigned int)(edTime.tv_sec - stTime.tv_sec), (unsigned int)(edTime.tv_usec - stTime.tv_usec));

    }

}

Compile the code using the command below,

gcc -o fibo2 fibo2.c

A sample run is as below,

Image may be NSFW.
Clik here to view.

Figure 3. Execution of Dynamic Programming Version Improved

References:
1. Algorithms. Dasgupta, C.H. Papadimitriou, and U. V. Vazirani, 2006
2. Wikipedia Fibonacci Number: http://en.wikipedia.org/wiki/Fibonacci_number


Viewing all articles
Browse latest Browse all 15

Trending Articles