主講人: jserv / 課程討論區: 2023 年系統軟體課程
返回「Linux 核心設計/實作」課程進度表Image Not Showing Possible ReasonsLearn More →
- The image file may be corrupted
- The server hosting the image is unavailable
- The image path is incorrect
- The image format is not supported
2023 年已變更作業要求Image Not Showing Possible ReasonsLearn More →
- The image file may be corrupted
- The server hosting the image is unavailable
- The image path is incorrect
- The image format is not supported
ktimer
, copy_to_user
一類的核心 API參照以下材料理解 Fibonacci 數列和對應的計算手法:
依據 Fibonacci and Golden Ratio Formulae,考慮 Fibonacci 最初提到不會死亡的兔子繁衍總量問題,假設成年兔子為 a
,幼年兔子為 b
,我們可得到以下關係:
將上述推導寫成矩陣的形式就會變成
則
解說短片: The Fibonacci Q-matrix
接著談及 Fast Doubling 手法,繼續整理:
因此可得:
根據 Fibonacci 數列原始定義 F(0) = 0, F(1) = 1, F(2) = 1
我們就可用這三個值,依據上述公式推導出隨後的數值。
對應的虛擬碼如下:
Fast_Fib(n)
a = 0; b = 1; // m = 0
for i = (number of binary digit in n) to 1
t1 = a*(2*b - a);
t2 = b^2 + a^2;
a = t1; b = t2; // m *= 2
if (current binary digit == 1)
t1 = a + b; // m++
a = b; b = t1;
return a;
以
可見遞迴次數縮減,還能再更快嗎?再觀察到
和最初的 Fibonacci 數列定義相比,可見相當大的差距。
示範案例:
求解
1010 = 10102
i | start | 4 | 3 | 2 | 1 | result |
---|---|---|---|---|---|---|
n | - | 1010 | 1010 | 1010 | 1010 | - |
F(m) | F(0) | F(0*2+1) | F(1*2) | F(2*2+1) | F(5*2) | F(10) |
a | 0 | 1 | 1 | 5 | 55 | 55 |
b | 1 | 1 | 2 | 8 | 89 | - |
對照
1110 = 10112
1 | 0 | 1 | 1 | result | |
---|---|---|---|---|---|
F(n) | F(0*2+1) | F(1*2) | F(2*2+1) | F(5*2+1) | F(11) |
a | 1 | 1 | 5 | 89 | 89 |
b | 1 | 2 | 8 | 144 |
許多現代處理器提供 clz / ctz 一類的指令,可搭配上述 Fast Doubling 手法運用:
0
1
可對照 你所不知道的 C 語言: 遞迴呼叫篇。
電腦在計算亂數時,常以新產生出來的數值作為下一次計算的依據,這就是為什麼計算機隨機數大部分都會表示成遞迴定義的數列。
這裡只探討 Pseudo-Random Number Generators (PRNG)
這是一般的 Fibonacci 數列
f[0] = 0;
f[1] = 1;
f[i] = f[i - 1] + f[i - 2];
數列呈現單調遞增
1, 1, 2, 3, 5, 8, 13, 21, ...
如果我們強迫 Fibonacci 數列的數值超出 100 之後折回來
f[0] = 0;
f[1] = 1;
f[i] = (f[i - 1] + f[i - 2]) % 100;
一開始雖然還是看得到規則,不過整體趨勢已經不再是單調遞增,當數值折回之後規律變得不太明顯
1, 1, 2, 3, 5, 8, 13, 21, 34, 55,
89, 44, 33, 77, 10, 87, 97, 84, 81, 65,
46, 11, 57, 68, 25, 93, 18, 11, 29, 40,
...
甚至可將 Fibonacci 的遞迴數列改成:
f[0] = 18;
f[1] = 83;
f[2] = 4;
f[3] = 42;
f[4] = 71;
f[i] = (f[i - 2] + f[i - 5]) % 100;
這個數列的規則已不容易看穿
18, 83, 4, 42, 71, 60, 54, 64, 96, 35,
56, 89, 20, 85, 55, 41, 44, 61, 29, 16,
70, 60, 31, 89, 47, 59, 7, 90, 96, 37,
...
這種產生隨機數的方法,稱為 Lagged Fibonacci generator (LFG),是電腦產生隨機數的一種方法。
〈Linux 核心的 hash table 實作〉提到,Linux 核心採用的雜湊函數稱為 Fibonacci hashing,其精神也依循上述,從而降低碰撞。
延伸閱讀: