patterncMinor
My C code for Fibonacci Sequence
Viewed 0 times
codeforfibonaccisequence
Problem
I've been learning more programming in the past few years (C, Java, Arduino) for my hobbies. I read the "C for Dummies" book and found that it was good, but did not cover much - especially pointers... One of my friends from college (CS major) suggested a simple program exercise to see if I could figure out how to use pointers. Well, I had to refer to a pdf of Ritchie's text "The C Programming Language" to learn about pointers. He asked me to make a program that returns the Fibonacci sequence. A month or so ago, I sent him my program, but he hasn't had time to review it since he is very busy with work these days. Basically what I am wondering about my program is if it is redundant or "too verbose" - basically is it written efficiently? IMO, as a hobbyist programmer, it works just fine.
Below is the source code file he initially sent to me:
Below is my version of the program that I sent to him for review:
```
/**
* @file fibonacci.cpp
*
* @brief Prints out a partial Fibonacci sequence.
*/
#include
unsigned int n;
char nMax[3]; //user input for sequence up to and including value @ this index
int Nmax;
// Function prototype for fibonacci()
unsigned int Fibonacci(unsigned int);
int main(int argc, char** argv)
{
printf("Please input the Nth index of the last sequence value.\n");
printf("Program will return entire Fibonacci Sequence up to and including Nth value.\n");
gets(nMax);
Nmax =atoi(nMax);
for (n = 0; n < Nmax; ++n)
{
Below is the source code file he initially sent to me:
/**
* @file fibonacci.cpp
*
* @brief Prints out a partial Fibonacci sequence.
*/
#include
// Function prototype for fibonacci()
unsigned int Fibonacci(unsigned int);
int main(int argc, char** argv)
{
printf("Fibonacci Sequence:\n");
for (unsigned int n = 0; n < 10; ++n)
{
unsigned int fib = Fibonacci(n);
printf("%d ", fib);
}
return 0;
}
// Computes the Nth Fibonacci number.
unsigned int Fibonacci(unsigned int N)
{
// Actual implementation goes here!!
}Below is my version of the program that I sent to him for review:
```
/**
* @file fibonacci.cpp
*
* @brief Prints out a partial Fibonacci sequence.
*/
#include
unsigned int n;
char nMax[3]; //user input for sequence up to and including value @ this index
int Nmax;
// Function prototype for fibonacci()
unsigned int Fibonacci(unsigned int);
int main(int argc, char** argv)
{
printf("Please input the Nth index of the last sequence value.\n");
printf("Program will return entire Fibonacci Sequence up to and including Nth value.\n");
gets(nMax);
Nmax =atoi(nMax);
for (n = 0; n < Nmax; ++n)
{
Solution
Doesn't work
The program doesn't work for me. Example:
The problem is that the array
Fixes
-
To fix problem #1, you can declare your
-
To fix problem #2, you should not assume that an entry in
Rewrite
I have rewritten your function with the two problems fixed:
This rewrite also:
Simpler way
You might also want to consider a simpler function that doesn't use an array of precomputed values. Calculating a fibonacci number can be done in a simple loop like this:
The program doesn't work for me. Example:
$ ./fibonacci
Please input the Nth index of the last sequence value.
Program will return entire Fibonacci Sequence up to and including Nth value.
10
1 1 2 3 1 0 1 1 2 3
The problem is that the array
tempseq is a temporary local variable, which means that every time you call the function Fibonacci(), that variable becomes unitialized. Your code is doing two things wrong:- It assumes that
tempseqwill contain the values that it had from previous invocations of the functionFibonacci().
- It assumes that
Fibonacci()will be called in a loop from 0 to n. If you just calledFibonacci(10)directly, it would not work because it depends on the answers for 8 and 9 being precomputed.
Fixes
-
To fix problem #1, you can declare your
tempseq array using the static keyword. This makes the array persist across invocations. You can think of it like if the static keyword made the tempseq variable into a global variable.-
To fix problem #2, you should not assume that an entry in
tempseq is necessarily valid. You can do something like check if the entry is 0. If it is zero, then the entry must be computed, otherwise it is valid to use.Rewrite
I have rewritten your function with the two problems fixed:
#define FIBMAX 100
// Computes the Nth Fibonacci number.
unsigned int Fibonacci(unsigned int n)
{
// FibResult is a persistent array of already computed values.
// We initialize fibResult[0] and [1] to take care of special cases.
static unsigned int fibResult[FIBMAX] = { 1, 1 };
// Guard against bad input.
if (n >= FIBMAX)
return 0;
if (fibResult[n] == 0) {
// We have not previously computed this entry, so compute it now
// using the recurrence relation.
//
// Note: calling Fibonacci(n-1) guarantees that fibResult[n-2] will
// be set, so we just use that to avoid one function call. We
// could have written this and it would have worked just fine:
//
// fibResult[n] = Fibonacci(n-1) + Fibonacci(n-2);
//
fibResult[n] = Fibonacci(n-1) + fibResult[n-2];
}
return fibResult[n];
}This rewrite also:
- Replaces the magic number 100 with a defined constant and checks the input so that we don't have any buffer overflow problems.
- Takes care of the special cases of n=0 and n=1 by filling in those entries in the
fibResultarray.
Simpler way
You might also want to consider a simpler function that doesn't use an array of precomputed values. Calculating a fibonacci number can be done in a simple loop like this:
unsigned int Fibonacci(unsigned int n)
{
unsigned int f1 = 1;
unsigned int f2 = 1;
for (unsigned int i = 0; i < n; i++) {
f2 = f1 + f2;
f1 = f2 - f1;
}
return f1;
}Code Snippets
#define FIBMAX 100
// Computes the Nth Fibonacci number.
unsigned int Fibonacci(unsigned int n)
{
// FibResult is a persistent array of already computed values.
// We initialize fibResult[0] and [1] to take care of special cases.
static unsigned int fibResult[FIBMAX] = { 1, 1 };
// Guard against bad input.
if (n >= FIBMAX)
return 0;
if (fibResult[n] == 0) {
// We have not previously computed this entry, so compute it now
// using the recurrence relation.
//
// Note: calling Fibonacci(n-1) guarantees that fibResult[n-2] will
// be set, so we just use that to avoid one function call. We
// could have written this and it would have worked just fine:
//
// fibResult[n] = Fibonacci(n-1) + Fibonacci(n-2);
//
fibResult[n] = Fibonacci(n-1) + fibResult[n-2];
}
return fibResult[n];
}unsigned int Fibonacci(unsigned int n)
{
unsigned int f1 = 1;
unsigned int f2 = 1;
for (unsigned int i = 0; i < n; i++) {
f2 = f1 + f2;
f1 = f2 - f1;
}
return f1;
}Context
StackExchange Code Review Q#124103, answer score: 4
Revisions (0)
No revisions yet.