一、斐波那契數列(Fibonacci Sequence)的定義
斐波那契數列的發明者,是意大利數學家列昂納多·斐波那契(Leonardo Fibonacci,生於公元1170年,卒於1240年,籍貫大概是比薩)。
斐波那契數列指的是這樣一個數列:1、1、2、3、5、8、13、21、……
這個數列從第三項開始,每一項都等於前兩項之和。如果設F(n)爲該數列的第n項(n∈N+)。那麼這句話可以寫成如下形式:
F(0) = 0,F(1)=1,F(n)=F(n-1)+F(n-2) (n≥2),
二、Fibonacci數列公式推導
可採用特徵方程法:
對於數列F(n),遞推公式爲F(n+1)=pF(n)+qF(n-1),其特徵方程爲x^2=px+q 即x^2-px-q=0,
1、 若方程有兩相異根α,β,則F(n)=c1·α^(n-1)+c2·β^(n-1);··
2、 若方程有兩等根α=β,則F(n)=(c1+nc2)·α^(n-1),
其中 c1,c2 可由初始條件確定,初始條件通常爲F(1)與F(2)。
根據特徵方程法,可以推出 Fibonacci 數列的第 n 項的公式爲(n = 1,2,.....):
三、Fibonacci 數列計算源代碼
- /******************************************************************************
- Copyright by Javacode007, All rights reserved!
- Filename : Fibonacci.c
- Author : Javacode007
- Date : 2012-8-4
- Version : 1.0
- Description : 斐波那契(Fibonacci)數列算法演示
- ******************************************************************************/
- #include <stdio.h>
- #include <time.h>
- #include <math.h>
- #define ITEM (sqrt(5))
- unsigned int Fibonacci_recursive(unsigned int n)
- {
- if(0 == n || 1 == n)
- {
- return 1;
- }
- return (Fibonacci_recursive(n - 1) + Fibonacci_recursive(n -2));
- }
- unsigned int Fibonacci(unsigned int n)
- {
- unsigned int a = 0;
- //float b = sqrt(5);
- //a = (pow((1 + b)/2, n + 1) - pow((1 - b)/2, n + 1))/b;;
- a = (pow((1 + ITEM)/2, n + 1) - pow((1 - ITEM)/2, n + 1))/ITEM;;
- return a;
- }
- int main()
- {
- int n = 40;
- clock_t start, end;
- int ret = 0;
- start = clock();
- ret = Fibonacci_recursive(n);
- end = clock();
- printf("Fibonacci(%u) = %u , Time Cost: %f s\r\n", n, ret, (float)(end - start)/CLOCKS_PER_SEC);
- start = clock();
- ret = Fibonacci(n);
- end = clock();
- printf("Fibonacci(%u) = %u , Time Cost: %f s\r\n", n, ret, (float)(end - start)/CLOCKS_PER_SEC);
- return 0;
- }
注: 源代碼的第27、 28 行已經註釋,而是利用宏定義替換計算5的平方根, 從而避免浮點數計算帶來的累積誤差,感興趣的朋友可以試試,對比兩者的計算結果^_^
輸出結果如下:
若將 n 修改爲 45, 則計算結果如下:
四、總結
通過對比計算 Fibonacci 數列的兩種計算方式,可以很明顯的看出, 採用公式法, 計算速度遠遠大於遞歸計算方法。因此,我們在遇到類似遞歸數列時,首先應該分析,通過推導出線性遞推數列的通項公式,用公式代替遞歸計算,將提高計算速度,並降低內存消耗。