# 2023q1 Homework3 (fibdrv)
contributed by < `bonianlee` >
:::danger
不要打錯自己的 GitHub 帳號
:notes: jserv
:::
## 開發環境
```bash
$ gcc --version
gcc (Ubuntu 11.3.0-1ubuntu1~22.04) 11.3.0
$ lscpu
Architecture: x86_64
CPU op-mode(s): 32-bit, 64-bit
Byte Order: Little Endian
Address sizes: 39 bits physical, 48 bits virtual
CPU(s): 6
On-line CPU(s) list: 0-5
Thread(s) per core: 1
Core(s) per socket: 6
Socket(s): 1
NUMA node(s): 1
Vendor ID: GenuineIntel
CPU family: 6
Model: 158
Model name: Intel(R) Core(TM) i5-9500 CPU @ 3.00GHz
Stepping: 10
CPU max MHz: 4400.0000
CPU min MHz: 800.0000
BogoMIPS: 6000.00
Virtualization: VT-x
L1d cache: 192 KiB
L1i cache: 192 KiB
L2 cache: 1.5 MiB
L3 cache: 9 MiB
NUMA node0 CPU(s): 0-5
```
<s>
## 完成進度
</s>
:::danger
不用抄題目,show me the code!
:notes: jserv
:::
## 開發過程
### 正確顯示 $fibonacii(100)$
根據〈[費氏數列分析](https://hackmd.io/@sysprog/fibonacci-number)〉,費氏數列 (Fibonacci sequence) 若以 64 位元來表示的話,正確的數值最高只能夠顯示到第 92 項 $fibonacii(92)$ ,因為當 $fibonacii(n), n > 92$ 時,會因為數值超過 64 位元所能表示的最大值,而造成溢位 (overflow) 的發生
在原始程式碼 [fibdrv](https://github.com/sysprog21/fibdrv) 中,費氏數列是以 64 位元的資料型態 `long long` 來表示,實際運行的結果顯示為
```c
f(93) fail
input: 7540113804746346429
expected: 12200160415121876738
```
與預期的結果相同,當數列計算到 $f(93)$ 時,會因為溢位而導致系統報錯,且顯示的輸出結果也與預期的不同,為了要解決這種狀況,我參考〈[Small/Short String Optimization 的實作](https://github.com/AdrianHuang/fibdrv/tree/big_number)〉以及 [qwe661234](https://github.com/qwe661234/fibdrv) 的實作
解決方式是將數字改以字串 (string) 的形式進行運算並且表示結果的值,首先定義結構體
```c
typedef struct str{
char numberStr[106];
}str_t;
```
接著計算費氏數列的部份,因為只會用到加法,故實作字串的加法,以下為部份程式碼
```c
static void add_str(char *a, char *b, char *out)
{
size_t size_a = strlen(a), size_b = strlen(b);
int i, sum, carry = 0;
if (size_a >= size_b) {
for (i = 0; i < size_b; i++) {
sum = (a[i] - '0') + (b[i] - '0') + carry;
out[i] = '0' + sum % 10;
carry = sum / 10;
}
for (i = size_b; i < size_a; i++) {
sum = (a[i] - '0') + carry;
out[i] = '0' + sum % 10;
carry = sum / 10;
}
if (carry)
out[i++] = '0' + carry;
out[i] = '\0';
}
```
前述的程式碼在做兩個數字字串的相加,其作法是十進位制每一個位數個別做相加,將進位存在 `carry` 當中,而 `out` 則用來儲存 `a` 與 `b` 相加的數字字串結果
而因為 `out` 是從低位數排列到高位數的字串,故在輸出結果時會將 `out` 做反轉,使最終結果方便閱讀,以下結果是計算到 $fibonacii(100)$ 的結果
```c
...
Reading from /dev/fibonacci at offset 98, returned the sequence 135301852344706746049
Reading from /dev/fibonacci at offset 99, returned the sequence 218922995834555169026
Reading from /dev/fibonacci at offset 100, returned the sequence 354224848179261915075
```
### 時間測量與效能分析