Fibonacci數列各語言實現的比較

  最近突然想了解一下函數式語言的內容,就找了本Haskell的書試了試,還別說,真的發現很多有趣的地方。以下,就是我在嘗試的一個例子:sql

Fibonacci數列,定義:編程

f(1) = 1,ide

f(2) = 1,函數

f(n) = f(n-1)+f(n-2)性能

使用C實現代碼以下:spa

  
  
  
  
  1. #include "stdio.h" 
  2. #include "stdlib.h" 
  3.  
  4. int fib(int n) 
  5.     if (n < 3) 
  6.         return 1; 
  7.     return fib(n-1)+fib(n-2); 
  8.  
  9. int main(int argc, char* argv[]) 
  10.     int n = 30; 
  11.     if (argc >= 2) 
  12.         n = atoi(argv[1]);   
  13.     printf("%d\n",fib(n));   
  14.     return 0; 

運行結果以下:遞歸

fibs 30: 832040, 0.091sip

fibs 40:102334155, 0.54sci

fibs 50:  -298632863, 1mstring

能夠看到,隨着n的增大,運行時間成指數級別增加,並且,fibs 50開始,因爲數據已經超過了int的範圍,後面的值已經有問題了。

 

而按照Haskell的教科書上的方法,Haskell的代碼以下:

  
  
  
  
  1. fibs n 
  2.     |n<3 = 1 
  3.     |otherwise =fibs(n-1)+fibs(n-2) 
  4.      
  5. main = print(fibs 30) 

運行結果:

fibs 30:832040, 1s

fibs 40:102334155 4s

fibs 50:12586269025, 6m27s

結果是對的,可是速度仍是比C的要慢上很多。感受體現不出函數式語言的優點啊。

懷着這樣的疑問,在網上問了一些大牛。原來是我尚未擺脫命令式編程的固有思惟。

上面兩段代碼,不管是C的仍是Haskell的,核心思惟就是一個遞歸的思路,在n增大的狀況下,遞歸的堆棧會迅速增大,形成性能的急劇下降。

而大牛們給出的函數以下:

  
  
  
  
  1. fibs = 1:1:zipWith (+) fibs (tail fibs) 
  2. main = print(fibs !! 29) 

是否是感受很是簡潔,讓咱們看看他的性能:

fibs 30: 832040,0.6s

fibs 40:102334155,0.7s

fibs 50:12586269025, 0.9s

是否是很強悍,時間基本線性增加,讓咱們看一個更大的例子:

fibs 100:354224848179261915075, 1s

fibs 1000:1s 

43466557686937456435688527675040625802564660517371780402481729089536

555417949051890403879840079255169295922593080322634775209689623239873322471

161642996440906533187938298969649928516003704476137795166849228875

fibs 10000:1s
33644764876431783266621612005107543310302148460680063906564769974680081442
16666236815559551363373402558206533268083615937373479048386526826304089246
30564318873545443695598274916066020998841839338646527313000888302692356736
13135117579297437854413752130520504347701602264758318906527890855154366159
58298727968298751063120057542878345321551510387081829896979161312785626503
31954871402142875326981879620469360978799003509623022910263681314931952756
30227837628441540360584402572114334961180023091208287046088923962328835461
50577658327125254609359112820392528539343462090424524892940390170623388899
10858410651831733604374707379085526317643257339937128719375877468974799263
05837065742830161637408969178426378624212835258112820516370298089332099905
70792006436742620238978311147005407499845925036063356093388383192338678305
61364353518921332797329081337326426526339897639227234078829281779535805709
93691049175470808931841056146322338217465637321248226383092103297701648054
72624384237486241145309381220656491403275108664339451751216152654536133311
13140424368548051067658434935238369596534280717687753283482343455573667197
31392746273629108210679280784718035329131176778924659089938635459327894523
77767440619224033763867400402133034329749690202832814593341882681768389307
20036347956231171031012919531697946076327375892535307725523759437884345040
67715555779056450443016640119462580972216729758615026968443146952034614932
29110597067624326851599283470989128470674086200858713501626031207190317208
60940812983215810772820763531866246112782455372085323653057759564300725177
44315051539600905168603220349163222640885248852433158051534849622434848299
38090507048348244932745373262456775587908918719080366205800959474315005240
25327097469953187707243768259074199396322659841474981936092852239450397071
65443156421328157688908058783183404917434556270520223564846495196112460268
31397097506938264870661326450766507461151267752274862159864253071129844118
26226610571635150692600298617049454250474913781151541399415506712562711971
33252763631939606902895650288268608362241082050562430701794976171121233066
073310059947366875
 
如今更能感受到Haskell的強大了吧。這樣的大數,通常的命令式語言都很難處理的。而用Haskell基本上能在很短期內完成精確的計算工做。
我也剛開始看Haskell兩天,就感覺到了它在數值處理方面的強大之處,相信隨着瞭解的逐步深刻,Haskell能給我更多的驚喜吧。
相關文章
相關標籤/搜索