Fibonacci數列第N項的兩種計算方法比較

一、斐波那契數列(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數列公式

 

三、Fibonacci 數列計算源代碼

 

  1. /****************************************************************************** 
  2. Copyright by Javacode007, All rights reserved! 
  3. Filename    : Fibonacci.c 
  4. Author      : Javacode007 
  5. Date        : 2012-8-4 
  6. Version     : 1.0 
  7. Description : 斐波那契(Fibonacci)數列算法演示 
  8. ******************************************************************************/  
  9. #include <stdio.h>  
  10. #include <time.h>  
  11. #include <math.h>  
  12.   
  13. #define ITEM (sqrt(5))  
  14.   
  15. unsigned int Fibonacci_recursive(unsigned int n)  
  16. {  
  17.     if(0 == n || 1 == n)  
  18.     {  
  19.         return 1;  
  20.     }  
  21.     return (Fibonacci_recursive(n - 1) + Fibonacci_recursive(n -2));  
  22. }  
  23.   
  24. unsigned int Fibonacci(unsigned int n)  
  25. {  
  26.     unsigned int a = 0;  
  27.     //float b = sqrt(5);  
  28.     //a = (pow((1 + b)/2, n + 1) - pow((1 - b)/2, n + 1))/b;;  
  29.       
  30.     a = (pow((1 + ITEM)/2, n + 1) - pow((1 - ITEM)/2, n + 1))/ITEM;;  
  31.   
  32.     return a;  
  33. }  
  34.   
  35. int main()  
  36. {  
  37.     int n = 40;  
  38.     clock_t start, end;  
  39.     int ret = 0;  
  40.   
  41.     start = clock();  
  42.     ret = Fibonacci_recursive(n);  
  43.     end = clock();  
  44.     printf("Fibonacci(%u) = %u , Time Cost: %f s\r\n", n, ret, (float)(end - start)/CLOCKS_PER_SEC);  
  45.   
  46.     start = clock();  
  47.     ret = Fibonacci(n);  
  48.     end = clock();  
  49.     printf("Fibonacci(%u) = %u , Time Cost: %f s\r\n", n, ret, (float)(end - start)/CLOCKS_PER_SEC);  
  50.   
  51.     return 0;  
  52. }  

 

 

注: 源代碼的第27、 28 行已經註釋,而是利用宏定義替換計算5的平方根, 從而避免浮點數計算帶來的累積誤差,感興趣的朋友可以試試,對比兩者的計算結果^_^
  輸出結果如下:

 

若將 n 修改爲 45, 則計算結果如下:

 

四、總結


          通過對比計算 Fibonacci 數列的兩種計算方式,可以很明顯的看出, 採用公式法, 計算速度遠遠大於遞歸計算方法。因此,我們在遇到類似遞歸數列時,首先應該分析,通過推導出線性遞推數列的通項公式,用公式代替遞歸計算,將提高計算速度,並降低內存消耗。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章