Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 4 years ago.
Improve this question
I am trying (and failing) to print the fibonacci sequence using recursion. I'm sure this is very very basic but I can't seem to get it.
Please tell me what I am doing wrong, thanks!
#include <stdio.h>
int fib(int a, int i)
{
int nextnum, num1 = nextnum - 1, num2 = nextnum - 2;
for (i = 0; i >= a; i++) {
nextnum = num1 + num2;
printf("%d", nextnum);
i++;
fib(a, i);
}
}
int main(void)
{
int a, i = 0;
printf("Enter a number for fib series: ");
scanf("%d", &a);
if (a == 1 || a == 2) {
printf("Enter higher number please!\n");
}
else {
fib(a, i);
}
}
Fibonacci numbers are often used as an intro into recursion because they are naturally recursive. In fact, implementing them recursively is trivial in any language. On a side note, it is usually not the best way to implement Fibonacci sequence for practical purposes.
By definition, Fib(X) = Fib(X - 1) + Fib(X - 2). This is recursion right there. The only thing which is missing is how we stop the recursion, and we know that Fib(0) is the same as Fib(1) and is 1.
How do we translate this to the C language? Very simple, almost one-to-one mapping!
unsigned int fib(unsigned int k) {
// First, check our exit (stop) conditions:
if (k == 0 || k == 1) return 1;
// Now recursive part
return fib(k - 1) + fib(k - 2);
}
Almost every recursion function contains two part : the particular part and then the recursive part.
So to write this function your algorithm will look like this
if (condition_separate_particular_part)
{
//here the code for part
}
else
{
//the recursive part
}
Now to determine the recursive part you will try to find how to explain the element "i" using it's predecessor elements "i-1" "i-2" ....
Like this it will be easy for you every time.
Note that sometimes it's useful to start to find iterative way to make it easy for your self.
I'm damn sure that you are new so that's why you feel lost a bit. But trust me you will habit soon if you exercise more. Try and you gonna see. ;).
Let me know if you find difficulties to find more exercises/examples. I will try to help you :).
Here is and example. Just type Exercise with solution for recursive functions on C and you will find a lot to exercise ;).
Now here both recursive and iterative code
Recursive
int fib(int n){
if (n < 2) // here is particular case
return n;
else // here is the recursion
return fib(n-1) + fib(n-2);
}
printf("%d\n", fib(10));
iterative
int fib(int n) {
int first = 0, second = 1;
int tmp;
while (n--) {
tmp = first+second;
first = second;
second = tmp;
}
return first;
}
Related
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.)
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.
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];
}
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);
}
#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;
}
}
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.
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;
}
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.
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 5 years ago.
Improve this question
This is my first time posting here, so forgive stupid mistakes if such happen.
I am a beginner in C coding (learning right now), and frankly not much of a math genius so the problem I encountered stumps me quite a bit. I found a solution to it by the way of testing different things, but honestly I don't exactly understand why my solution does work, and the code before the solution applied doesn't.
The code is a binary search for a given number in a sorted array created by using seeded srand48, and sorted with a linear sort.
To frame the situation. Code before the solution did work well until array reached 45 elements, then it stopped finding the number.
Before the solution code:
bool search(int value, int values[], int n)
{
int first, middle, last;
first = 0;
last = n - 1;
middle = (first + last) / 2;
if (n > 0)
{
while (first < last)
{
if (values[middle] == value)
{
return true;
}
else if (values[middle] < value)
{
first = middle + 1;
}
else
{
last = middle - 1;
}
middle = (first + last) / 2;
}
}
else
{
return false;
}
return 0;
}
The solution I found was just removing + and - 1 from the new middle value assignment. After I did this it works perfectly fine. What I would like to know for my own future reference and learning is why exactly the first code does not work, and why did that solution fix it. (I might somehow subconsciously understand how this works and that is why I came up with the fix, but I can't consciously figure out the logic behind it.)
There are some subtle problems in your code:
It does not work if the array has a single element: it will always return 0. This problem is actually causing your observed behavior: you test while (first < last) but first and last are both included in the range to search. You should either use while (first <= last) or change the algorithm to exclude last, which I favor, as you no longer need to special case the empty array with this solution.
It can return false or 0 in case of failure, which is OK in C but different in javascript. You should remove the else clause.
The computation for middle has a potential arithmetic overflow if n is larger than half the maximum value if int and the value is large enough. This is actually a classic bug that remained in hiding for many years in many standard C libraries. Instead of middle = (first + last) / 2, you should use:
middle = first + (last - first) / 2;
Here is a corrected and simplified version:
bool search(int value, int values[], int n) {
int first = 0, last = n;
while (first < last) {
int middle = first + (last - first) / 2;
if (values[middle] == value) {
return true;
}
if (values[middle] < value) {
first = middle + 1;
} else {
last = middle;
}
}
return false;
}
Note that the middle value where value was found is not necessarily the smallest index where is appears if there are duplicates in the array. It is not a problem here as you are only interested in the boolean result, but the algorithm must altered if you want to find the smallest index.
Matt Timmermans posted a better algorithm in another question that is both more efficient and has this property:
bool search(int value, int values[], int n) {
int pos = 0;
int limit = n;
while (pos < limit) {
int middle = pos + ((limit - pos) >> 1);
if (values[middle] < value)
pos = middle + 1;
else
limit = middle;
}
return pos < n && values[pos] == value;
}
As to your final question: why does removing the + 1 and -1 from your code fix the problem? Your fix does not fully correct the problem: your changes have this effect:
first = middle; is just suboptimal, the search will take marginally longer but no other effect.
last = middle; fixes the problem because the loop assumes last to be excluded, which is consistent with last = middle;.
The remaining problem is the initial value for last, which should be last = n;.
With last = n - 1;, you will still fail to locate the value if it is at the end of the array without duplicates, including if the array has only one element.
I have written a small program to calculate the factorial of a number using Dynamic Programming Technique.
#include<stdio.h>
int fact(int n)
{
int f[n],i;
f[0] = 1;
for(i=1;i<=n;i++)
f[i] = i * f[i-1];
return f[n];
}
int main(void)
{
printf("\n Factorial of %d is %d ",5,fact(5));
return 0;
}
Is the approach of memorization correct? Because, dynamic programming involves recursion. But I have not included it here. So I am not sure of my approach.
Yes, your approach of solving the problem is a very simple case of Dynamic Programming, where you store previously solved sub-problems to help you solve the actual problem. While the example you provided would be considered Dynamic Programming, it usually isn't called Memoization
When someone says Memoization, it usually involves in a top-down approach of solving problems, where you assume you have already solved the sub-problems by structuring your program in a way that will solve sub-problems recursively.
You store, or memoize, the results of these sub-problems so that they will not be computed multiple times.
Let me illustrate Memoization through an example:
Here is a simple example of computing the nth Fibonacci of a number:
int fib(int n)
{
if (n <= 1)
return n;
return fib(n-1) + fib(n-2);
}
The above code uses recursion to solve sub-problems (fib(n-1) and fib(n-2)) so that fib(n) can be solved in the end. It assumes that fib(n-1) and fib(n-2) are already solved in the way that it is structured.
Though this code looks elegant, the running time is exponential, because you can solve fib(i), where i is a number less than n, multiple times. You can look at the diagram presented here to see the tree generated by this problem: http://www.geeksforgeeks.org/program-for-nth-fibonacci-number.
To avoid the unnecessary re-computation, Memoization is used to optimizes run-time by using memory.
Here is an optimized example of computing the nth Fibonacci number using Memoization:
/*Global array initialized to 0*/
int a[100];
int fib(int n)
{
/*base case*/
if (n <= 1)
return n;
/*if fib(n) has not been computed, compute it*/
if (a[n] == 0) {
a[n] = fib(n - 1) + fib(n - 2);
}
*/Otherwise, simply get a[n] and return it*/
return a[n];
}
As you can see, the overall structure is not that much different from the recursive solution, but it runs linear time instead of exponential time because fib(i) will only be computed only if we have not computed already.
If I were to use your approach, Dynamic Programming, for the Fibonacci problem, it would look something like this:
int fib(int n)
{
/* just like the array you declared in your solution */
int f[n+1];
int i;
/* set up the base cases, just like how you set f[0] to 1*/
f[0] = 0;
f[1] = 1;
for (i = 2; i <= n; i++)
{
/* using previously solved problem to solve further problems*/
f[i] = f[i-1] + f[i-2];
}
/*return the final result*/
return f[n];
}
There are more subtle differences, trade offs, and implications between Dynamic Programming and Memoization. Some consider Memoization a subset of Dynamic Programming. You can read more about the difference here:
Dynamic programming and memoization: bottom-up vs top-down approaches
Yes this is dynamic programming : going from base cases up to final case. Of course your example (factorial) is too simple so you have been able to simplify many things by yourself : you eliminated the recursion and never use a test in the memoization. But anyway that's it.
For the general scheme of memoization see http://en.wikipedia.org/wiki/Memoization.
For explanation about Dynamic programming see http://en.wikipedia.org/wiki/Dynamic_programming, you will be able to read the section about Fibonacci sequence and its computation using a bottom-up approach.
Hello getting better at C everyday, this is a example problem out of my textbook that generates fibonacci numbers and shows recursive functions. The program works but I just don't understand how... Specifically in parts (looper % 5), the whole functionfib and what printf(", %8ld", fib(looper)); is doing. Is it like saying fib() do x amount of times. If this problem is not easy to explain then could someone show me a easier way to understand how recursive functions work other then "towers of hanoi" example. Thanks.
NOTE: program is meant to handle up to 30 numbers others wise it starts to look ugly.
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
long fib (long num);
int main(void)
{
int seriesSize;
printf("This program will print out a Fibonacci series.\n");
printf("How many many numers do you wnat? ");
scanf_s("%d", &seriesSize);
printf("First %d Fib numbers: \n", seriesSize);
for (int looper = 0; looper < seriesSize; looper++)
{
if (looper % 5)
{
printf(", %8ld", fib(looper));
}
else
{
printf("\n%8ld", fib(looper));
}
}
printf("\n");
return 0;
}
long fib(long num)
{
if (num == 0 || num == 1)
{
return num;
}
return (fib(num - 1) + fib(num - 2));
}
The idea behind the long fib(long num) function is that it mirrors the natural definition of the fibonacci sequence in that it is defined in terms of itself. That is, fib(n) is defined by fib(n-1) and fib(n-2). For example, fib(5) is fib(4)+fib(3).
The textbook has written the function in a recursive manner as described above. Note that this is not the most efficient way to implement a fibonacci function but it does logically make sense.
To understand it, it pays to trace through its execution with an example input. Take fib(3) for example. The first if statement doesn't trigger because num is not 0 or 1. Thus, it works out what fib(2) and fib(1) are, and adds them together. We know what fib(1) does - it returns 1 in the first if statement. Trace through fib(2) in a similar manner and you'll see that it returns 1. Thus, fib(3) will return fib(2)+fib(1)=2. You can extend this further - take fib(4). It will return fib(3)+fib(2), which we know are 2 and 1, hence fib(4) = 3.
This approach can be taken for most recursive functions - think of it as creating new instances of the fib() function which continually creates until it "bottoms out" at an end case (num == 1 or num == 0, in this case), and returns back up, filling in the answers until you get back to the function you started with, with the answer.
"How to write an algorithm that, given a number n, prints out all the simplified vulgar fractions that have the denominator 1..n"
(I hope I could phrase it well, feel free to rephrase.)
Example: If n is 3, the output should be like "1/2 1/3 2/3"
We were talking about this question in the end of the last class. He showed us a solution and asked us to try to understand the code. Here it is:
#include<stdio.h>
void main()
{
int p,m,n,i,j,a,b;
p=7;
m=0;
n=1;
do
{
printf("%d/%d\n",m,n);
i=j=1;
for(b=2; b<=p; b++)
{
a=m*b/n+1;
if(a*j<b*i)
{
i=a;
j=b;
}
}
m=i;
n=j;
}
while(i<j);
}
I'm new to C and just learning to code, to be honest I couldn't figure out what this code does. And it also prints "0/1", I also wonder why that is, I think it shouldn't be printing that.
Here is my elementary approach to this problem:
#include <stdio.h>
int gcd(int a, int b) // Finds the GCD of two numbers.
{
int temp;
while (a) {
temp = a;
a = b % a;
b = temp;
}
return b;
}
int main(void)
{
int i, j;
for (i = 1; i <= 7; i++) // Denominator goes from 1 to 7
for (j = 1; j < i; j++) // Numerator goes from 1 to denominator
if (gcd(i, j) == 1)
printf("%d/%d ", j, i); // If the numerator and the denominator
// are coprimes then print the fraction
return 0;
}
"n" is 7 in both of the codes. I checked the execution times with much bigger numbers and my algorithm is faster than the other one. So I don't understand what the other code is for. Also any suggestions/corrections about my code is appreciated.
Your professor's code looks like it may have been purposely complicated, maybe as a learning exercise. If that's the case, I can't say I agree with the practice.
Your approach of nested for loops is exactly how I would have approached the solution.
And it also prints "0/1", I also wonder why that is, I think it shouldn't be printing that.
Simply put, it prints "0/1" because of this line:
printf("%d/%d\n",m,n);
The values m and n are initialized to 0 and 1 right before the do loop, so on the first pass it prints exactly that.
Your code is better than the first paste in a few ways. The loop over b is a crappy way of trying to find a common prime factor for m and n. But it only runs to b=7, so the first program can print 11/121 and other non-reduced fractions!
If the loop over b were properly coded, it would take O(sqrt(n)) time. Your gcd() (using the Euclidean Algorithm well) has O(log(n)) time.
The other code is exceptionally poorly written. Single-letter variables for non-idiomatic uses? void main()? No comments? Nobody should be expected to understand that code, and especially not learners.
Your code seems pretty competent - it's far clearer and cleaner than the other code and pretty much superior in every way. The only suggestion I would make is, firstly, you should take in N as user input from the console, to make rerunning the program for different values simpler, and you should also comment the GCD function explaining it's operations.