# 2025q1 Homework5 (assessment)
contributed by < `Hande1004` >
## 改進測驗題
[W2Q1](https://hackmd.io/@sysprog/linux2025-quiz2#%E6%B8%AC%E9%A9%97-1)
這題目標是使用 Linux 核心風格 List API 的簡化標頭檔 list.h 來開發快速排序程式碼。
為了把順序打亂來測試快速排序,用了 `random_shuffle_array()` 這個函式,而這之中負責打亂主要函式為 `getnum()` ,然而,這個函式以三個固定初始值的 `static uint16_t` 變數為種子,搭配固定的模數與乘數進行遞迴運算。這種設計屬於簡易的 deterministic pseudo-random number generator,其輸出完全由初始值決定,缺乏真正的隨機性來源。
因此,我決定改進這個部份,運用第一份作業(lab0)的 qtest.c 所寫到的 `os_random()` 函式來改寫。
```c
uint8_t os_random(void)
{
int seed = rand();
/* ASLR makes the address random */
uintptr_t x = (uintptr_t) &os_random ^ seed;
struct timespec time;
clock_gettime(CLOCK_MONOTONIC, &time);
x ^= (uintptr_t) time.tv_sec;
x ^= (uintptr_t) time.tv_nsec;
return x;
}
```
接著我使用亂數品質分析工具 ENT,分別對 `getnum()` 與 `os_random()` 這兩個亂數產生函式進行測試。每個函式皆透過迴圈呼叫 100,000 次,每次產生一個 uint16_t 型態的亂數,總計輸出 200,000 bytes 的隨機資料,作為 ENT 測試的輸入樣本。
```C
int main()
{
srand(time(NULL));
for (int i = 0; i < 100000; i++) {
uint16_t x = get_unsigned16();
fwrite(&x, sizeof(x), 1, stdout);
}
return 0;
}
```
然後得到輸出結果。
`getnum()`:
```
Entropy = 7.700204 bits per byte.
Optimum compression would reduce the size
of this 200000 byte file by 3 percent.
Chi square distribution for 200000 samples is 76186.12, and randomly
would exceed this value less than 0.01 percent of the times.
Arithmetic mean value of data bytes is 121.7062 (127.5 = random).
Monte Carlo value for Pi is 3.301473015 (error 5.09 percent).
Serial correlation coefficient is 0.006997 (totally uncorrelated = 0.0).
```
`os_random()`:
```
Entropy = 7.999027 bits per byte.
Optimum compression would reduce the size
of this 200000 byte file by 0 percent.
Chi square distribution for 200000 samples is 270.05, and randomly
would exceed this value 24.73 percent of the times.
Arithmetic mean value of data bytes is 127.2464 (127.5 = random).
Monte Carlo value for Pi is 3.126991270 (error 0.46 percent).
Serial correlation coefficient is 0.000427 (totally uncorrelated = 0.0).
```
首先,`os_random()` 的熵為 7.999 bits/byte,幾乎達到理論最大值 8,代表每個 byte 的資訊含量非常接近理想的完全隨機。而 `getnum()` 僅達 7.70。
卡方分布也顯示了明顯差異:`os_random()` 的值為 270.05(約有 24.73% 機率自然超過此值),而 `getnum()` 高達 76186.12,遠遠偏離正常範圍,代表其 byte 值分布極不均勻。
## 紀錄閱讀〈因為自動飲料機而延畢的那一年〉的啟發
就像作者一開始說,以為做飲料機很簡單,只要
> 落下杯子、移動杯子,加茶、加糖、加冰塊、加珍珠、再搖一搖、封模,一條龍一氣呵成的設備,操作者只要會按按鈕就行了。
然而直到作者與他們的團隊真的開始動手實作,才發現問題接踵而至,也才意識到自己其實什麼都不懂。看到這裡,也讓我想起之前看過的達克效應:正因為自身認知不足,才會以為生活中的許多例子都是理所當然。就像作者所提到的,當開始遇到許多機械問題時,他們才意識到自己對機械相關的知識幾乎是零,這也導致了許多問題的發生。
例如在冰塊的運輸過程中,因製造商與測量儀器精度不足,導致誤差累積,冰塊有時會卡住。但這些問題,往往必須等到製造商實際製作後,才能夠被測試及發現問題。接著又必須重新改進設計,再送回製造商製作,而這樣的來回過程就會耗費不少時間。
這堂課上,老師經常提醒我們:我們來這裡,就是為了解決真實世界的問題。然而,現實世界的問題,往往比我們想像的還要複雜許多——不是光靠想一想、說一說,事情就能順利完成。真正的挑戰,往往藏在那些繁瑣的細節之中。唯有不斷精進自己的技術與知識,讓 know-how 更加全面且深入,我們才能在面對真實世界的難題時迎刃而解。
在文中,作者遇到了一個很大的困難,就是分配冰塊的問題,這個問題可以看得出作者當時的無力感及絕望。
> 冰塊分配是個遠比我想像中困難的問題,就算液壓機可以凹出螺旋來,光是調整線徑和螺距就不知道要跑幾趟工廠。就算加工螺旋的問題解決了,後頭還有一坨拉庫的問題,諸如驅動螺旋的馬達挑選、符合食品安全等級的軸承、冰斗的形狀,我們甚至還沒解決冰塊黏在一起的問題。
我覺得,這些一次次的失敗,又或是好不容易想了一個辦法,卻發現這個方法依然不可行,這些種種真的會逐漸磨耗一個人的意志與鬥志。原本滿腔的熱血,經過多次的挫折後,也慢慢被澆熄了。換作是我,或許也會開始懷疑:「不如乾脆放棄吧,找個輕鬆一點的任務,做完就算,何必這樣折磨自己?」文中的作者,也曾經陷入這樣的心境:
> 這個領域實在是太過廣博,現實如同真理般,給予和狂妄自負的傢伙相對應的絕望,對於沒有準備好的人毫不留情。我覺得自己像無頭蒼蠅一樣亂撞,做什麼都徒勞無功。我內心一直浮現「我是不是挑錯專案了」。之後還要延畢一學期, 然後又不會設計機構, 只能幫忙打雜。我問好友是不是該把這專案停掉, 先去做其他感覺比較能學習到東西的事,例如去其他公司實習之類的,他們沒辦法給出能說服我的建議。
然後故事的轉折是與 jserv 老師的聊聊後,讓作者重新找回繼續作的動力,老師說的一些話也讓我感觸很深。
> 不能現在就放棄,要是現在就放棄的話,你這輩子日後遇到這種等級的困難,就只會想逃避而已。
在我做這幾週作業的過程中,也曾無數次想過要放棄。因為許多作業的難度,是我過去從未遇過的挑戰,也涉及很多我從來沒學過的觀念與知識。每當卡關時,真的會懷疑自己到底能不能撐下去。
但我也告訴自己,如果現在一遇到困難就選擇逃避,那未來科技發展得越來越快,進入業界後遇到更大的挑戰時,難道也要用逃避來面對嗎?想到這裡,我就會咬著牙,逼自己再撐一下。正如老師常說的:「不懂不可恥,缺什麼就補什麼。」那些不會的知識,只要肯學,自然就會了。真正可惜的是還沒努力就選擇放棄。