2013年2月27日 星期三

[C Programming] 擴充Fibonacci數-延伸

請參見擴充Fibonnaci數
延伸問題:
1. 請問再給了n之後這個程式一共用了多少個乘法,多少個加法。
2. 請用陣列的功能改寫這個程式,請問效率會有所改善嗎?
    請證實您的想法;如果沒有,用陣列豈不沒多大意義?
3. 這個題目不過是Fibonacci數的擴充,而用矩陣可以得到很高效率的程式,
    那麼有沒有辦法用矩陣的方式來解這個題目呢?
    提示:請考慮下式並化簡。
    An+1 = X*An-1 + Y*(An-Fn) + Fn + Fn+1
              = X*An-1 + Y*An + (1-Y)Fn + Fn+1
    這個解法來自Jan Tijmen Udding。
4. 請仔細研究一下我們的程式,或使用的式子,找出可以省略下來的運算,
    並且改良此地的程式(這是一個極為簡單的練習,您應該要試一試)。

個人解答:
1.
從i = 2開始到i = n,一共是n-1個迴圈。
計算fn+1是2乘法1加法,計算An+1是2乘法3加法。
如果不算那個減法,也不把i++當成加法的話,
一共使用了(n-1)(4m+4p)=4(n-1)(m+p)的運算,m表乘法p表加法。
2.
基本上如果我們從小到大計算的話,計算次數仍然會相同,
但會省略掉遞移值的動作,理論上會速度稍微快上一點點,
但記憶體使用空間也算是效率的一環,所以方法不變的話,
只是拿兩者來交換而已。
但還有一個好處是我們可以記錄下前面的Fn和An值,
這會使得重複查詢可以反覆利用。
3.
我們把式子後面兩項再化簡一下:
   (1-Y)Fn + Fn+1
= (1-Y)Fn + Y*Fn + X*Fn-1
= Fn + X*Fn-1
我們可以把式子寫成矩陣的關係式,
左邊的四項為An+1, Fn+1, An   , Fn,
右邊的四項為An    , Fn    , An-1, Fn-1,
則中間的四階矩陣為:
y 1 x x
0 y 0 x
1 0 0 0
0 1 0 0
利用這個矩陣的次方來做像之前那樣子的運算。
值得注意的是,這當中有4個被標藍色的位置無論如何都是0。
有興趣的話可以自行做一次乘法試試看。
最後求出來以後,將第一行的值相乘加總就可以得到An了!
4.
這裡最簡單的省略就是將迴圈結束條件設為i <= n-1。
然後在其後我們算出tmpfn1和tmpAn1後return tmpAn1即可,
這樣我們就不用做最後一次值的遞移。

沒有留言:

張貼留言