3

This is my idea of solving 'nth term of fibonacci series with least processing power'-

int fibo(int n, int a, int b){
    return (n>0) ? fibo(n-1, b, a+b) : a;
}

main(){
    printf("5th term of fibo is %d", fibo(5 - 1, 0, 1));
}

To print all the terms, till nth term,

int fibo(int n, int a, int b){
    printf("%d ", a);
    return (n>0)? fibo(n-1, b, a+b): a;
}

I showed this code to my university professor and as per her, this is a wrong approach to solve Fibonacci problem as this does not abstract the method. I should have the function to be called as fibo(n) and not fibo(n, 0, 1). This wasn't a satisfactory answer to me, so I thought of asking experts on SOF.

It has its own advantage over traditional methods of solving Fibonacci problems. The technique where we employ two parallel recursions to get nth term of Fibonacci (fibo(n-1) + fibo(n-2)) might be slow to give 100th term of the series whereas my technique will be lot faster even in the worst scenario.

To abstract it, I can use default parameters but it isn't the case with C. Although I can use something like -

int fibo(int n){return fiboN(n - 1, 0, 1);}
int fiboN(int n, int a, int b){return (n>0)? fiboN(n-1, b, a+b) : a;}

But will it be enough to abstract the whole idea? How should I convince others that the approach isn't wrong (although bit vague)?

(I know, this isn't sort of question that I should I ask on SOF but I just wanted to get advice from experts here.)

5
  • 6
    I’m confused. Since you’re not using the a and b for anything, why are they there? And doesn’t this return zero in all cases anyway? Commented Aug 14, 2018 at 18:48
  • 1
    Indeed, as @SamiKuhmonen said, this code will always return 0. Perhaps your professor was wanting you to fix this problem instead of the 'abstraction' problem? In my eyes, the 'abstraction' problem really isn't a problem, but more of a feature as you can specify starting values for the fibonacci calculator. Commented Aug 14, 2018 at 18:55
  • 1
    Have you tested your idea? Does it work? I don't think the 5th Fibonacci number is zero but perhaps I miss something? Commented Aug 14, 2018 at 19:18
  • The 5th fibonacci number is the 4th plus the 3rd. So try to calculate the 4th number. That's the 3rd plus the 2nd. So calculate the 3rd.... it's the 2nd plus the 1st. I think you're on the right track, holding on to more than one number, but the extra numbers you're passing around when you call fibo(5,0,1) are the first and second, and those aren't useful when calculating the 5th. Commented Aug 14, 2018 at 20:32
  • Oh, my bad. There was a typo in my code. It should return a instead of 0. And more or less, it works. Please recheck the code. Commented Aug 16, 2018 at 1:25

7 Answers 7

4

With the understanding that the base case in your recursion should be a rather than 0, this seems to me to be an excellent (although not optimal) solution. The recursion in that function is tail-recursion, so a good compiler will be able to avoid stack growth making the function O(1) soace and O(n) time (ignoring the rapid growth in the size of the numbers).

Your professor is correct that the caller should not have to deal with the correct initialisation. So you should provide an external wrapper which avoids the need to fill in the values.

int fibo(int n, int a, int b) {
    return n > 0 ? fibo(b, a + b) : a;
}
int fib(int n) { return fibo(n, 0, 1); }

However, it could also be useful to provide and document the more general interface, in case the caller actually wants to vary the initial values.

By the way, there is a faster computation technique, based on the recurrence

fib(a + b - 1) = f(a)f(b) + f(a - 1)f(b - 1)

Replacing b with b + 1 yields:

fib(a + b) = f(a)f(b + 1) + f(a - 1)f(b)

Together, those formulas let us compute:

fib(2n - 1) = fib(n + n - 1)
            = fib(n)² + fib(n - 1)²

fib(2n)     = fib(n + n)
            = fib(n)fib(n + 1) + fib(n - 1)fib(n)
            = fib(n)² + 2fib(n)fib(n - 1)

This allows the computation to be performed in O(log n) steps, with each step producing two consecutive values.

Sign up to request clarification or add additional context in comments.

4 Comments

Thank you very much for the correction. That was exactly what I had coded originally but I made a typo while posting the question. But how is number of steps calculated for a particular solution? IDK this but probably from my general understanding, my solution will take exactly (n -1) steps. Please correct me, if I'm wrong.
@vivek: fibo gets called n+1 times since the last call has n=0
but since I'm calling it with initial value of n as n-1, will it not run for n-1 times plus the original call ((n-1) + 1 = n)?
@vivek: i don't think that is correct; F(1) is 1, not 0. F(0) is 0. Anyway, it's really not important; as n gets bigger, the difference between n+1 and n gets successively less significant.
2

Your result will be 0, with your approaches. You just go in recursion, until n=0 and at that point return 0. But you have also to check when n==1 and you should return 1; Also you have values a and b and you do nothing with them.

i would suggest to look at the following recursive function, maybe it will help to fix yours:

int fibo(int n){
    if(n < 2){
        return n;
    }
    else 
    {
       return (fibo(n-1) + fibo(n-2));    
    }
}

It's a classical problem in studying recursion.

EDIT1: According to @Ely suggest, bellow is an optimized recursion, with memorization technique. When one value from the list is calculated, it will not be recalculated again as in first example, but it will be stored in the array and taken from that array whenever is required:

const int MAX_FIB_NUMBER = 10;

int storeCalculatedValues[MAX_FIB_NUMBER] = {0};

int fibo(int n){

    if(storeCalculatedValues[n] > 0)
    {
        return storeCalculatedValues[n];
    }

    if(n < 2){
        storeCalculatedValues[n] = n;
    }
    else 
    {
       storeCalculatedValues[n] = (fibo(n-1) + fibo(n-2));
    }
    return storeCalculatedValues[n];
}

7 Comments

That's incredibly inefficient.
I agree, but is recursion.
Nice answer. I think it would be helpful if you could include the memoization technique in your example so that you would also have given a more efficient program in your answer.
I know about this approach, my professor taught us exactly this method to solve the problem. Please look at the modified code, there was one typo.
The problem with the above mentioned approach is, it builds up two parallel stacks in memory for solving each new term of series. This way, to calculate 1000th term, it will take minutes (may be faster) to come up with the solution. But in my suggested method, it remembers the last two terms of fibonacci and gives nth term without needing to start from scratch every time, as in traditional method.
|
1

Using recursion and with a goal of least processing power, an approach to solve fibonacci() is to have each call return 2 values. Maybe one via a return value and another via a int * parameter.

The usual idea with recursion is to have a a top level function perform a one-time preparation and check of parameters followed by a local helper function written in a lean fashion.


The below follows OP's idea of a int fibo(int n) and a helper one int fiboN(int n, additional parameters)

The recursion depth is O(n) and the memory usage is also O(n).

static int fib1h(int n, int *previous) {
  if (n < 2) {
    *previous = n-1;
    return n;
  }
  int t;
  int sum = fib1h(n-1, &t);
  *previous = sum;
  return sum + t;
}

int fibo1(int n) {
  assert(n >= 0); // Handle negatives in some fashion
  int t;
  return fib1h(n, &t);
}

Comments

1
#include <stdio.h>
int fibo(int n);//declaring the function.

int main()
{
    int m;
    printf("Enter the number of terms you wanna:\n");
    scanf("%i", &m);
    fibo(m);
    for(int i=0;i<m;i++){
        printf("%i,",fibo(i)); /*calling the function with the help of loop to get all terms */
    }
    return 0;
}

int fibo(int n)
{ 
    if(n==0){
        return 0;
    }
    if(n==1){
        return 1;
    }

    if (n > 1)
    {
        int nextTerm;
        nextTerm = fibo(n - 2) + fibo(n - 1); /*recursive case,function calling itself.*/
         return nextTerm;
    }
}

1 Comment

This is the very basic solution of fibonacci series, using recursion method.
0

solving 'nth term of fibonacci series with least processing power'

I probably do not need to explain to you the recurrence relation of a Fibonacci number. Though your professor have given you a good hint.

Abstract away details. She is right. If you want the nth Fibonacci number it suffices to merely tell the program just that: Fibonacci(n)

Since you aim for least processing power your professor's hint is also suitable for a technique called memoization, which basically means if you calculated the nth Fibonacci number once, just reuse the result; no need to redo a calculation. In the article you find an example for the factorial number.

For this you may want to consider a data structure in which you store the nth Fibonacci number; if that memory has already a Fibonacci number just retrieve it, otherwise store the calculated Fibonacci number in it.

By the way, didactically not helpful, but interesting: There exists also a closed form expression for the nth Fibonacci number.

This wasn't a satisfactory answer to me, so I thought of asking experts on SOF.

"Uh, you do not consider your professor an expert?" was my first thought.

2 Comments

Yes, her answer wasn't satisfactory to me. The abstraction thing was added by me while posting the question, she didn't mention it at all. Please recheck the original code again, I've corrected the typo.
"if you calculated the nth Fibonacci number once, just reuse the result; no need to redo a calculation" this is exactly my concern for those other solutions. If I wish to print 100 terms of Fibonacci series, there'll be a need to call the fibo() 100 times + internally whatever calls it makes as in " return fibo(n-1) + fibo(n-2)". For the memorization thing, if I follow one of the techniques as one mentioned in @simion 's answer, do you think creating one global array is a good idea?
0

As a side note, you can do the fibonacci problem pretty much without recursion, making it the fastest I know approach. The code is in java though:

public int fibFor() {
    int sum = 0;
    int left = 0;
    int right = 1;
    for (int i = 2; i <= n; i++) {
        sum = left + right;
        left = right;
        right = sum;
    }
    return sum;
}

2 Comments

Yeah, I'm very well aware of this approach. Since the actual module that we were taught was Recursion, we had to implement everything using this concept only. Thank you for your suggestions btw.
Even the factorial thing, when implemented through simple looping constructs is pretty fast, consumes less/almost no stack memory and simple to understand but again University needs us to implement all those things with those cumbersome recursive methods even if they are hundred times less efficient.
0

Although @rici 's answer is mostly satisfactory but I just wanted to share what I learnt solving this problem. So here's my understanding on finding fibonacci using recursion-

  • The traditional implementation fibo(n) { return (n < 2) n : fibo(n-1) + fibo(n-2);} is a lot inefficient in terms of time and space requirements both. This unnecessarily builds stack. It requires O(n) Stack space and O(rn) time, where r = (√5 + 1)/2.
  • With memoization technique as suggested in @Simion 's answer, we just create a permanent stack instead of dynamic stack created by compiler at run time. So memory requirement remains same but time complexity reduces in amortized way. But is not helpful if we require to use it only the once.
  • The Approach I suggested in my question requires O(1) space and O(n) time. Time requirement can also be reduced here using same memoization technique in amortized way.
  • From @rici 's post, fib(2n) = fib(n)² + 2fib(n)fib(n - 1), as he suggests the time complexity reduces to O(log n) and I suppose, the stack growth is still O(n).

So my conclusion is, if I did proper research, time complexity and space requirement both cannot be reduced simultaneously using recursion computation. To achieve both, the alternatives could be using iteration, Matrix exponentiation or fast doubling.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.