基於Cache的Fibonacci數列的計算

2021-07-22 13:38:00 字數 2088 閱讀 6025

這個數列在編寫程式的過程中,應該被無數次提起,今天再次提起,作為動態規劃的乙個引入。

動態規劃被人總結為:

遞推 + cache

而使用cache方式的fib數列計算也是很酷的。**非常簡潔,但是如果沒有這種思想,就很難理解為什麼這麼寫了。

另一種情況是,我們知道要用個陣列去快取,但是在具體實現的過程中,就很難翻譯成**,這裡姑且當作一種反思吧。

ok,先看**:

#define maxn 45

#define unknown -1

#include

long f[maxn+1]; //用於快取已經計算的陣列

long fib_c(int n)

return f[n];

}long fib_c_driver(int n)

return(fib_c(n)); //計算

}int main(void)

首先如果計算乙個斐波那契數,我們呼叫fib_c_driver函式。這個函式將會把快取陣列初始化,前兩個數是我們已知的0,1,第三個開始到以後都看作未知,初始化為-1,這個數字隨便寫,但是不要是乙個可能的斐波那契數。

然後將呼叫fib_c函式去遞迴計算,這個過程稍微解釋一下:

進來以後,先判斷陣列中是否已經快取,如果沒有快取,就遞迴計算。

如果求的是fib_c(0), fib_c(1),直接返回已經有的數值。

如果求得是fib_c(2),一看,陣列中沒有快取,於是計算f[2] = f[1] + f[0],但是這麼寫就不對,因為f[1],f[0]也是需要計算得來。因為0,1開始就知道,如果計算的是f[45], 直接返回了f[44] + f[43],那麼得到的是-2,根本不是我們想要的數,所以,f[2] 後面寫的是fib_c(1) + fib_c(0)。

廣義一些即為:f[n] = fib_c(n-1) + fib_c(n-2);

那麼這個與平常寫的那個遞迴有何區別呢?

我們看f[4] = fib_c(3) + fib_c(2),轉換成去求fib_c(3)和fib_c(2)。

fib_c(3)進來是判斷f[3] == unknown,結果是f[3]已經快取好了,不用再去計算。同樣f[2]也是這樣。

這裡用樹形圖展開,如果未加快取的計算,將是這棵樹的深度優先遍歷,每乙個樹枝都將被走一遍。而如果是快取,則只需要走最左邊的那個路徑:f(6 ) –> f(5)–>f(4)–>f(3)–>f(2)–>f(1),f(0),然後整個陣列就被寫好了。這下減掉多少樹枝!

當然,你能感受到,既然是簡單的快取資料,幹嘛還要用遞迴的方式去快取呢?直接來不就好~

以下:

//非遞迴呼叫版本

long fib_dp(int n)

return f[n];

}

這個簡潔到不用解釋了。比上面遞迴的版本要優秀一些。但是上面的遞迴大概也可以看作走到這裡的快取吧!

到這裡似乎可以結束了,但是我們看到,當我們計算時,需要開闢乙個陣列,儲存了從0,1,1,2,3,5….所有的資料,這…是不是有點奢侈?

對的,雖然時間寶貴,空間也相當寶貴。

我們計算時,當前的狀態僅僅與回退到之前的兩個狀態相關,那麼是否可以只用乙個變數解決這種問題呢?

答案是可以的。

long fib_ultimate(int n)

for(int i = 2; i < n; i++)

return back1 + back2;

}

這就有了一些動態規劃中,狀態轉移方程的意思了!

但是值得注意的是,優化了空間後,取得單個斐波那契數值加快了,但是並不儲存過去的值。即,計算fib(45),就是單純的計算出這個值,這個過程中產生的其他值都被拋棄了。再需要fib(45),或者fib(30)等,需要重新計算。如果基於陣列的快取,計算fib(45)後,從fib(0)到fib(45)的值,隨用隨取,可以做到在o(1)內得到結果。所以,具體問題具體分析。時間優化是必要之舉,空間優化適當選擇。

基於cache的攻擊方式

1,flush reload 攻擊者和受害者之間使用共享記憶體,導致這種攻擊的可行性,由於頁面重複資料刪除和共享庫,許多平台上都可以使用共享記憶體。攻擊者可以利用clflush指令簡單的重新整理目標位址,在經過一定的時間間隔後,攻擊者再去重新訪問目標的位址並測量出時間間隔。如國被攻擊方在時間間隔中訪...

基於Cache資料庫的資料重複驗證

此方法基於cache資料庫的索引結構,根據資料rowid,code,desc進行資料重複驗證,確保插入資料的code及desc欄位保持唯一約束 creator 李欣 creatdate 2017 08 05 description 資料校驗方法 根據索引校驗 和描述是否存在 table user.m...

Cache的替換策略

根據程式區域性性規律可知 程式在執行中,總是頻繁地使用那些最近被使用過的指令和資料。這就提供了替換策略的理論依據。綜合命中率 實現的難易及速度的快慢各種因素,替換策略可有隨機法 先進先出法 最近最少使用法等。1.隨機法 rand法 隨機法是隨機地確定替換的儲存塊。設定乙個隨機數產生器,依據所產生的隨...