Below is my code for Fibonacci sequence, however when I use a large number such as 100 or more it takes forever to produce output. Why? any help would be appreciated. :(

#include <iostream>

using namespace std;
long fib_num ( long  );



int main()
{


        long  num = 0;
        long  sequence = 0;

        cout << " Enter a positive number and I will compute the Fibonacci sequence for that number: ";
        cin >> num;
        if ( num < 0)
        {       cout << " Number must be greater than zero " << endl;
                return 1;
        }
        cout << endl << endl;

        sequence = fib_num(num);

        cout << " The " << num << "th number of the Fibonacci sequence is " << sequence << endl;

        return 0;
}

        long fib_num ( long n)
        {
                if ( n == 0)
                {
                        return 0;
                }

                else if ( n == 1 )
                {
                        return 1;
                }
                else
                        return  fib_num( n -1) + fib_num(n-2);
        }

<< moderator edit: added code tags: [code][/code] >>

Recommended Answers

All 22 Replies

Your fibonacci function runs in exponential time.

Let me put it this way:

Suppose that it takes 1 microsecond to compute fib_num(0) and fib_num(1).

Then, in computing fib_num(2), you'll call fib_num(0), which takes 1 microsecond (mms, I'll abbreviate), and fib_num(1), which also takes 1 mms. This means that fib_num(2) will take at least 2 mms.

Then, to compute fib_num(3), you will call fib_num(2), which takes at least 2 mms, and then fib_num(1), which takes 1 mms. So fib_num(3) takes at least 3 mms.

Continuing this pattern, fib_num(4) would take at least 5 mms, fib_num(5) would take 3 + 5 = 8 mms, and fib_num(6) would take 5 + 8 = 13 mms, at least.

This is actually the fibonacci pattern of growth in runtime. And the fibonacci pattern grows exponentially. You'll find that for large values of n (like 100), the time it takes to compute f(n) is about 1.618 times the amount of time it takes to compute f(n - 1). If fib_num(6) takes 13 microseconds, then fib_num(100) would take at least 1.618 to the 94th power times 13 microseconds. And 1.618**94 * 13 equals 5.74e20. This amount of microseconds is equal to 5.74e14 seconds. Which is about 18 million years. You might as well get up for some coffee.

Even if you ran this program on a computer that was 10000 times faster (the times mentioned above are kind of slow by today's standards), it would still take at least 1819 years to compute. And computing fib_num(101) would take at least 2944 years to complete.

Notice that you recurse to fib_num(n-1) and fib_num(n-2). But in order to compute fib_num(n-1), you'll call fib_num(n-2) and fib_num(n-3). Notice that fib_num(n-2) is getting calculated multiple times. This is redundant.

In order to compute fib_num efficiently, you'll want to use a loop instead of recursion.

Numerous recursive calls of a function produce delays. The maths is done in the previous answer to your question by Rashakil Fol. Besides this sequence produces really big numbers. I changed the algorithm a bit and even the 50th member of the sequence goes over the boundaries of the long (at least on my machine). To save time though you can exchange the recursion with a simple for loop. I think the algorithm should be right.

long fib_num ( long n)
{
     long last=2;     // temporary "last" number in the sequence
     long blast=1;    // one before the temporary "last"
     long sum;

     switch(n) {
               case 0: return 0;
                    break;
               case 1: return 1;
                    break;
               case 2: return 2;
                    break;
               default: for(long i=3; i != n; i++) {
                                 sum=blast+last;
                                 blast=last;
                                 last=sum;
                        }
                        return sum;
                    break;
     }
}

Maybe something simpler...

long fib_num(long n)
{
	long low(0), high(1);

	while (n--) {
		high += low;
		low = high - low;
	}

	return low;
}

Maybe something simpler...

long fib_num(long n)
{
	long low(0), high(1);

	while (n--) {
		high += low;
		low = high - low;
	}

	return low;
}

Wouldn't that trap high at 1 and low at 0? Perhaps 1, 1 are what you meant as starting vars.

>however when I use a large number such as 100 or more it takes forever
It will also probably produce incorrect results. Fibonacci numbers grow at such a large amount that unless N is small, you'll overflow a long. Even using unsigned long to protect against undefined behavior and extend the range a bit, you can still only accurately produce fibonacci numbers up to a value of 45 (if I recall correctly) for N when long is 32 bits.

But the speed issue is the many, many unnecessary repeated calculations. You can fix it by using a non-recursive algorithm (as described by everyone else), or by saving the results in an array for the recursive algorithm and skipping the recursive calls if the result for a value has already been worked out:

#include <iostream>

// Slow textbook version
unsigned long fib1 ( unsigned long i )
{
  if ( i < 2 )
    return i;

  return fib1 ( i - 1 ) + fib1 ( i - 2 );
}

// Fast caching version
unsigned long fib2 ( unsigned long i )
{
  unsigned long x;
  static unsigned long save[45];

  if ( save[i] != 0 )
    return save[i];
  else if ( i < 2 )
    x = i;
  else
    x = fib2 ( i - 1 ) + fib2 ( i - 2 );

  return save[i] = x;
}

int main()
{
  std::cout<< fib1 ( 45 ) <<'\n';
  std::cout<< fib2 ( 45 ) <<'\n';
}

Wouldn't that trap high at 1 and low at 0? Perhaps 1, 1 are what you meant as starting vars.

Did you actually think through a few iterations of the loop?

I tried values 1 and 1 which made program work correctly. Thanks, for all the input everyone.

In response to Narue's fib2:

If we're going to have a static, fixed-length, read-only array, then heck,

unsigned long fib3 ( unsigned long i )
{
  static unsigned long save[45] = {0, 1, 1, 2, 3, 5, 8, 13, 21,
 34, 55, 89, 144, 233, 377, 610, 987, 1597, 2584, 4181,
 6765, 10946, 17711, 28657, 46368, 75025, 121393, 196418,
 317811, 514229, 832040, 1346269, 2178309, 3524578,
 5702887, 9227465, 14930352, 24157817, 39088169,
 63245986, 102334155, 165580141, 267914296, 433494437,
 701408733};

  return save[i];
}

>If we're going to have a static, fixed-length, read-only array, then heck
In real code, yea. But for learning purposes, that only teaches you to google for the first N fibonacci numbers.

#include <iostream.h>
#include <stdlib.h>

int fibonacci()
{
 unsigned long fib;
 cout << "Please input a number of fibonacci numbers which will be displayed: ";
 cin >> fib;
 unsigned long a = 1;
 unsigned long b = 1;
 unsigned long temp;
 for (int count1 = 0; fib != count1; count1 ++)
 {
  cout << a << " is the " << count1 + 1 << "th number\n";
  temp = b;
  b += a;
  a = temp;
 }
 return 0;
}

int main()
{
 fibonacci();
 cout << endl;
 system("PAUSE");
 return 0;
}
Member Avatar for iamthwee

Please check the date on the threads before you post.

Wouldn't that trap high at 1 and low at 0? Perhaps 1, 1 are what you meant as starting vars.

No, and it works perfectly. For example: the 10th of fibonacci:

high = 1   ; low = 0
------------------------
high = 1   ; low = 1
high = 2   ; low = 1
high = 3   ; low = 2
high = 5   ; low = 3
high = 8   ; low = 5
high = 13  ; low = 8
high = 21  ; low = 13
high = 34  ; low = 21
high = 55  ; low = 34
high = 89  ; [B]low = 55[/B]

Oh crap, I got fool :( Next time, I will check the date. (mad)

but how to determine whether if X is a term of the Fibonacci or not? (for last algorithm)

Wouldn't that trap high at 1 and low at 0? Perhaps 1, 1 are what you meant as starting vars.

yeah, its 1 1.
But now the problem is the long. This would work only till n = 46.
What if I wand fib (100)? Any suggestions?
Regards

It was slow, but it worked. Many many years ago I wrote a fibonacci generator using try/throw/catch exceptions in C++ as a test of the exception handling of various compilers of the time (about 20 years ago - a lot of them were buggy). I'd post it here, but the code is hiding on a floppy somewhere in my code library and my last computer with a floppy drive is in storage... :-( Oh, well. Anyway, it can be done, but not effectively for very large numbers! I think we stopped at 13 or so. Enough to test the compiler, but not so much as to overflow the stack.

In other history, I used fibonacci sequences in an index fund balancing program I wrote for a major investment fund back in 1984-85 in San Francisco. They had to rebalance the funds to track whatever indexes they were tied to every day, and this was for over $10B on the S&P500, Russel2000, etc. We were actually able to do that with PC's (with 8087 coprocessors), sucking down the close-of-day prices from the market data feeds, building up the model portfolios, and generating buy/sell orders for the open of the next day.

yeah, its 1 1.
But now the problem is the long. This would work only till n = 46.
What if I wand fib (100)? Any suggestions?
Regards

A recursive fib routine will crash and burn before you get to very big numbers. This is one of those situations where if your compiler can't do adequate optimization you are going to have to unroll it by hand. The algorithm is naturally recursive, and building an optimized version that is not means you will probably have to resort to the evil "goto" statement, and a lot of insidious cruft that you will NEVER want to look at again after it is working!

Ok. This is pretty snappy and using unsigned long long (64bit) values, you can get a fibonacci number up to about 100. On my system, there is no apparent delay from input to output of any number. In any case, for a 32bit integer (unsigned), fib(47) is as high as you can go before you wrap around. Not sure of the exact number, but I think a 64bit value gets you to about 100 or so. It definitely wraps shortly after that.

#include <stdlib.h>
#include <iostream>

using namespace std;

unsigned long long fib2(unsigned long long n)
{
    if (n == 0) return 0;
    if (n == 1) return 1;
    if (n == 2) return 1;
    return (fib2(n-1) + fib2(n-2));
}

unsigned long long fib( unsigned long long n )
{
   unsigned long long array[n];

   if (n <= 10) return fib2(n);

   // Build up array of 10 elements to work from
   for (unsigned long long i = 0; i < 10; i++)
   {
      array[i] = fib2(i);
   }

   // Populate the rest of the array by using the previously computed values.
   for (unsigned long long i = 10; i < n; i++)
   {
      array[i] = array[i-1] + array[i-2];
   }

   // Now return final value for N
   return array[n-1] + array[n-2];
}

int main( int argc, const char* argv[] )
{
    for (int i = 1; i < argc; i++)
    {
       cout << "fib(" << argv[i] << ") = " << dec << fib(strtoul(argv[i], 0, 10)) << endl;
    }
    return 0;
}
#include<iostream.h>
#include<conio.h>
void main()
{
clrscr();
long int f1=0,f2=1,f3;
int num;
cout<<"               Fibonacci Series ";
cout<<endl<<endl;
cout<<"Enter the number till which Fibonacci series is desired: ";
cin>>num;
cout<<"The series is : "<<endl;
if(num==0)
{
cout<<"";
}
else if(num==1)
{
cout<<"0";
}
else if(num==2)
{
cout<<"0 1 ";
}
else
{
cout<<"0 1 ";
for(int i=2;i<=num;i++)
{
f1=f1+f2;
f3=f1;
f1=f2;
f2=f3;
cout<<+f3<<" ";
}
}
getch();
}
commented: Resurrecting a 7 year old thread for bad unformatted code with no explanation why you resurrected it is strongly frowned upon. Especially when better code has been posted. -3

Couple things to point out. First void main() is NOT standard. main should ony return an int. Second your program is using depreciated headers. If you have an older compiler that does not support the new standard header I would suggest you get a new one. MSVC2010 express and Code::Blocks are both free modern compilers. Third you have no indentation. Proper indentation is key for good programing.

trying

#include "stdafx.h"


#include <list>
#include <deque>
#include <time.h>
#include <iostream>
#include <iomanip>
#include <string>
#include <algorithm>
#include <cassert>
#include <cstdlib>
#include <vector>



using namespace std;
using std::vector;


clock_t begin, end;
clock_t begin1, end1;

double diffclock(clock_t clock1,clock_t clock2)
{
    double diffticks=clock1-clock2;
    double diffms=(diffticks*10)/CLOCKS_PER_SEC;
    return diffms;
}


long fib(const long &x) {
    if( x <= 1 ) return x;
    return fib(x-1) + fib(x-2);
}

long fib2(long y) {
    if( y <=1 ) return y;

    vector<long> fibs;

    for(long f=0; f <= y; ++f ) {
        if( f <=1) fibs.push_back(f);
        else fibs.push_back(fibs[f-1] + fibs[f-2]);
    }
    return fibs[y];
}

long _tmain(long argc, _TCHAR* argv[])
{
    cout << "Fibonacci Series" << endl;
    long maxfib = 40;
    cout  << endl;
    begin1=clock();
    for(long i =0 ; i < maxfib ; ++i ) {
        begin=clock();
        cout << setw(10) << i << " : " << setw(10) << fib(i);
        end=clock();
        cout << setw(10) << double(diffclock(end,begin)) << endl;
    }
    end1=clock();
    cout << "Time taken by recursive methid is " << double(diffclock(end1,begin1)) << " ms\n\n" << endl;


    begin1=clock();
    for(long i =0 ; i < maxfib ; ++i ) {
        begin=clock();
        cout << setw(10) << i << " : " << setw(10) << fib2(i);
        end=clock();
        cout << setw(10) << double(diffclock(end,begin)) << endl;
    }
    end1=clock();
    cout << "Time taken by looping is " << double(diffclock(end1,begin1)) << " ms" << endl;
    return 0;
}

================= Results =====================
Fibonacci Series - comparing two methods runtime

   Itr          Fib #  Time(ms)
     0 :          0         0
     1 :          1         0
     2 :          1         0
     3 :          2         0
     4 :          3         0
     5 :          5         0
     6 :          8         0
     7 :         13         0
     8 :         21         0
     9 :         34         0
    10 :         55      0.16
    11 :         89         0
    12 :        144         0
    13 :        233         0
    14 :        377         0
    15 :        610         0
    16 :        987         0
    17 :       1597         0
    18 :       2584         0
    19 :       4181         0
    20 :       6765         0
    21 :      10946      0.15
    22 :      17711         0
    23 :      28657         0
    24 :      46368      0.16
    25 :      75025         0
    26 :     121393      0.16
    27 :     196418      0.31
    28 :     317811      0.31
    29 :     514229      0.63
    30 :     832040      1.09
    31 :    1346269      1.56
    32 :    2178309      2.66
    33 :    3524578      4.53
    34 :    5702887      7.19
    35 :    9227465     11.56
    36 :   14930352     19.22
    37 :   24157817        30
    38 :   39088169     49.69
    39 :   63245986     79.22

Time taken by recursive methid is 208.91 ms

     0 :          0      0.16
     1 :          1         0
     2 :          1         0
     3 :          2         0
     4 :          3         0
     5 :          5         0
     6 :          8         0
     7 :         13         0
     8 :         21         0
     9 :         34         0
    10 :         55         0
    11 :         89         0
    12 :        144         0
    13 :        233         0
    14 :        377         0
    15 :        610         0
    16 :        987         0
    17 :       1597         0
    18 :       2584         0
    19 :       4181      0.15
    20 :       6765         0
    21 :      10946         0
    22 :      17711         0
    23 :      28657         0
    24 :      46368         0
    25 :      75025         0
    26 :     121393         0
    27 :     196418         0
    28 :     317811         0
    29 :     514229         0
    30 :     832040         0
    31 :    1346269         0
    32 :    2178309         0
    33 :    3524578         0
    34 :    5702887         0
    35 :    9227465         0
    36 :   14930352         0
    37 :   24157817         0
    38 :   39088169         0
    39 :   63245986         0
Time taken by looping is 0.63 ms
Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.