chore(C): add fibonacci algorithm (#794)
parent
d253a29f96
commit
cef837425c
|
@ -36,6 +36,7 @@
|
||||||
- [Palindrome Number](maths/palindrome.c)
|
- [Palindrome Number](maths/palindrome.c)
|
||||||
- [Fibonacci Series](maths/fibonacci-series.c)
|
- [Fibonacci Series](maths/fibonacci-series.c)
|
||||||
- [Odd or Even Number](maths/odd-or-even-number.c)
|
- [Odd or Even Number](maths/odd-or-even-number.c)
|
||||||
|
- [Fibonacci Number](maths/fibonacci-number/README.md)
|
||||||
|
|
||||||
## Queues
|
## Queues
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,4 @@
|
||||||
|
main
|
||||||
|
# binary files
|
||||||
|
*.o
|
||||||
|
*.exe
|
|
@ -0,0 +1,4 @@
|
||||||
|
run: main.c
|
||||||
|
.\a.exe
|
||||||
|
main.c:
|
||||||
|
gcc .\src\main.c .\src\fib.c -lm
|
|
@ -0,0 +1,59 @@
|
||||||
|
# Fibonacci Number
|
||||||
|
Fibonacci numbers form a Fibonacci sequence where given any number (excluding first 2 terms) is a sum of its two preceding numbers. Usually, the sequence is either start with 0 and 1 or 1 and 1. Below is a Fibonacci sequnce starting from 0 and 1:
|
||||||
|
|
||||||
|
$$
|
||||||
|
0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, \dots
|
||||||
|
$$
|
||||||
|
|
||||||
|
The problem is to calculate the n-th term Fibonacci number given two starting numbers.
|
||||||
|
|
||||||
|
## Prerequisites
|
||||||
|
- C compiler (or IDE)
|
||||||
|
- MAKE software (optional if you compile the source files manually)
|
||||||
|
|
||||||
|
|
||||||
|
## Instructions
|
||||||
|
- using makefile
|
||||||
|
```bash
|
||||||
|
make # or mingw32-make
|
||||||
|
```
|
||||||
|
- compile using gcc
|
||||||
|
```
|
||||||
|
cd <path>\fibonacci-number
|
||||||
|
gcc .\src\main.c
|
||||||
|
```
|
||||||
|
## Note
|
||||||
|
The sequence can be described by a recurrent function as below:
|
||||||
|
|
||||||
|
$$
|
||||||
|
\begin{align*}
|
||||||
|
F(0) &= 0 \\
|
||||||
|
F(1) &= 1 \\
|
||||||
|
F(n) &= F(n-1) + F(n-2)
|
||||||
|
\end{align*}
|
||||||
|
$$
|
||||||
|
|
||||||
|
- This provides a direct recursive implementation. The time complexity is $O(2^n)$. It can be improved through memomization.
|
||||||
|
- It can done iteratively using 2 more states variables. The time complexity is $O(n)$.
|
||||||
|
- There exists a clever logarithmic algorithm $O(\log{n})$ in computing n-th term Fibonacci number. The computations can be in form of matrix multiplication, then we can devise some form of Ancient Egyptian multiplication (i.e.: double and squaring) to improve the algorithm. [reference](https://rybczak.net/2015/11/01/calculation-of-fibonacci-numbers-in-logarithmic-number-of-steps/)
|
||||||
|
- Lastly, there also exist a formula to approximate n-term Fibonacci number $O(1)$. [reference](https://mathworld.wolfram.com/BinetsFibonacciNumberFormula.html)
|
||||||
|
|
||||||
|
The given implementations shall assume that the Fibonacci sequence is starting from 0 and 1. The reader may try to generalize it to certain extent as a practice.
|
||||||
|
|
||||||
|
## Test Cases & Output
|
||||||
|
|
||||||
|
1. Example output of calling function:
|
||||||
|
```
|
||||||
|
/* some code */
|
||||||
|
printf("%d", iter_fib(7));
|
||||||
|
printf("%d\n", memo_fib(7));
|
||||||
|
/* some code */
|
||||||
|
```
|
||||||
|
|
||||||
|
```
|
||||||
|
13
|
||||||
|
13
|
||||||
|
```
|
||||||
|
2. The code should yield the same output as other version.
|
||||||
|
|
||||||
|
3. The sum of even Fibonacci numbers below 4000000 should be 4613732. [Adapted from Project Euler.net](https://projecteuler.net/problem=2)
|
|
@ -0,0 +1,92 @@
|
||||||
|
#include"fib.h"
|
||||||
|
#include<math.h> // sqrt, pow are used in binet_fib
|
||||||
|
|
||||||
|
int recur_fib(int n){
|
||||||
|
if(n == 0 || n == 1)
|
||||||
|
return n;
|
||||||
|
else
|
||||||
|
return recur_fib(n-1) + recur_fib(n-2);
|
||||||
|
}
|
||||||
|
int iter_fib(int n){
|
||||||
|
if(n == 0 || n == 1)
|
||||||
|
return n;
|
||||||
|
int prev2 = 0;
|
||||||
|
int prev1 = 1;
|
||||||
|
int res = prev1 + prev2;
|
||||||
|
for(n = n - 2; n > 0; --n){
|
||||||
|
prev2 = prev1;
|
||||||
|
prev1 = res;
|
||||||
|
res = prev1 + prev2;
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
// it should be called before using the function memo_fib()
|
||||||
|
void memomizing_fib(){
|
||||||
|
memomized_fib[0] = 0;
|
||||||
|
memomized_fib[1] = 1;
|
||||||
|
for(int i = 2; i < MAXSIZE; ++i)
|
||||||
|
memomized_fib[i] = memomized_fib[i-1]+memomized_fib[i-2];
|
||||||
|
}
|
||||||
|
|
||||||
|
// return memomized value if exists, or else compute it as usual
|
||||||
|
int memo_fib(int n){
|
||||||
|
if(n < MAXSIZE && n >= 0)
|
||||||
|
return memomized_fib[n];
|
||||||
|
else
|
||||||
|
return memo_fib(n-1) + memo_fib(n-2);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* fibonacci based linear transformation (linear algebra)
|
||||||
|
* reference: https://rybczak.net/2015/11/01/calculation-of-fibonacci-numbers-in-logarithmic-number-of-steps/
|
||||||
|
*/
|
||||||
|
int iter_log_fib(int n){
|
||||||
|
int a = 0;
|
||||||
|
int b = 1;
|
||||||
|
int p = 0;
|
||||||
|
int q = 1;
|
||||||
|
while(n > 0){
|
||||||
|
if(n%2 == 0){
|
||||||
|
int prev_p = p;
|
||||||
|
int prev_q = q;
|
||||||
|
p = prev_p*prev_p + prev_q*prev_q;
|
||||||
|
q = (2*prev_p + prev_q)*prev_q;
|
||||||
|
n = n/2;
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
int prev_a = a;
|
||||||
|
int prev_b = b;
|
||||||
|
--n;
|
||||||
|
a = p*prev_a + q*prev_b;
|
||||||
|
b = q*prev_a + (p+q)*prev_b;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* fibonacci based linear transformation (linear algebra)
|
||||||
|
* reference: https://rybczak.net/2015/11/01/calculation-of-fibonacci-numbers-in-logarithmic-number-of-steps/
|
||||||
|
*/
|
||||||
|
int log_fib_helper(int n, int a, int b, int p, int q){
|
||||||
|
if(n == 0)
|
||||||
|
return a;
|
||||||
|
else if(n%2 == 0)
|
||||||
|
return log_fib_helper(n/2, a, b, p*p+q*q, (2*p+q)*q);
|
||||||
|
else
|
||||||
|
return log_fib_helper(n-1, p*a + q*b, q*a+(p+q)*b, p, q);
|
||||||
|
}
|
||||||
|
|
||||||
|
int log_fib(int n){
|
||||||
|
return log_fib_helper(n,0,1,0,1);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Closed form formula
|
||||||
|
* reference: https://mathworld.wolfram.com/BinetsFibonacciNumberFormula.html
|
||||||
|
*/
|
||||||
|
int binet_fib(int n){
|
||||||
|
const double golden_ratio = (1+sqrt(5))/2;
|
||||||
|
const double conjugate_golden_ratio = 1-golden_ratio;
|
||||||
|
double res = (pow(golden_ratio,n) - pow(conjugate_golden_ratio, n))/sqrt(5);
|
||||||
|
return round(res);
|
||||||
|
}
|
|
@ -0,0 +1,22 @@
|
||||||
|
#ifndef FIB_H_INCLUDED
|
||||||
|
#define FIB_H_INCLUDED
|
||||||
|
|
||||||
|
/**
|
||||||
|
* fib(n) takes nonnegative number n
|
||||||
|
* return n-th term fibonacci number.
|
||||||
|
* The prefix highlights its algorithm used
|
||||||
|
*/
|
||||||
|
|
||||||
|
int recur_fib(int n);
|
||||||
|
int iter_fib(int n);
|
||||||
|
|
||||||
|
#define MAXSIZE 30
|
||||||
|
int memomized_fib[MAXSIZE];
|
||||||
|
void memomizing_fib(); // it should be called before using the function memo_fib()
|
||||||
|
|
||||||
|
int memo_fib(int n);
|
||||||
|
int iter_log_fib(int n);
|
||||||
|
int log_fib(int n);
|
||||||
|
int binet_fib(int n);
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,23 @@
|
||||||
|
#include<stdio.h>
|
||||||
|
#include"fib.h"
|
||||||
|
|
||||||
|
int main(){
|
||||||
|
memomizing_fib(); // this is to initialize the memomized table
|
||||||
|
int n = 15;
|
||||||
|
printf("%d\n", recur_fib(n)); // it becomes slow as n get larger for recur_fib
|
||||||
|
for(int i = 0; i <= 35; ++i){
|
||||||
|
printf("n = %d\t", i);
|
||||||
|
printf(" %d", iter_fib(i));
|
||||||
|
printf(" %d", memo_fib(i));
|
||||||
|
printf(" %d", log_fib(i));
|
||||||
|
printf(" %d", binet_fib(i));
|
||||||
|
printf(" %d\n", iter_log_fib(i));
|
||||||
|
}
|
||||||
|
int sum = 0;
|
||||||
|
int bound = 4000000;
|
||||||
|
for(int i = 0; memo_fib(i) < bound; ++i)
|
||||||
|
if(memo_fib(i)%2 == 0)
|
||||||
|
sum += memo_fib(i);
|
||||||
|
printf("The sum of even Fibonacci number below %d = %d", bound, sum);
|
||||||
|
return 0;
|
||||||
|
}
|
Loading…
Reference in New Issue