sysprog2018
主講人: jserv / 課程討論區: 2018 年系統軟體課程
在街上你隨意找一人,兩人同一天生日的可能性有多大?
貌似很渺茫,直觀來說。考慮到閏年,一年共有 366 天,遇到同一天生日的機率為 1/366
,或 0.0027%
。但是如果把問題改為:在一個房間裡,至少有多少人,才能使其中兩個人的生日是同一天的可能性超過 50%?如果生日的分佈是隨機事件,在機率的推算,前述問題只要 23 個人在場,即可達到其中至少兩個人同一天生日,聽起來很怪吧?
這個有趣的數學現象被稱為生日悖論。這不是一個真正的邏輯悖論,因為它不是自相矛盾的,只是非常地不直觀。
先假設一年只有 365 天,每一天的生日機率相同。生日悖論會令人感到難以置信,因為人類傾向於從自己的角度看待問題。人們通常這樣想,如果一個房間裡加上自己共有 23 人,你會覺得在這 22 人裡頭跟你同一天生日的可能性太低了。365 天,現在卻只有 22 個人,你可能會想機率只有 22/365
,所以很難在這 22 個人中遇上跟自己同一天生日。但這是錯的! —— 只是站在你自己的角度來思考有誰與你生日是一樣的。
事實上,生日問題指的是在任何 23 個人中,兩人生日相同的機率是多少。而不是你進入了一個有著 22 個人的房間,房間裡有人會和你有相同生日的機率。我們需要挨個比較房間裡每個人之間的生日。
ryanpatiency
把第一個人與其他 22 個比較,把第二個人與 21 個人比較,第三個人與其它 20 個人比較…直到最後第二個人與最後一個人比較。將 23 個人之間的所有這些比較加起來,產生 22 + 21 + 20 … + 1 = 23 × 22/2 = 253種不同的搭配,所以產生一對成功匹配的生日並非不可思議。
為了計算出生日相同的機率,我們可以先計算所有人生日都不同的機率。那麼,第一人生日是唯一的機率為 365/365
,第二個人生日是唯一的機率則下降到 364/365
,以此類推,第 23 個人生日是唯一的機率為 343/365
。
然後,把所有 23 個獨立機率相乘,即可得到所有人生日都不相同的機率為:(365/365) × (364/365) × … × (343/365) ,得出結果為 0.491
。那麼,再用 1 減去 0.497
,就可以得到 23 個人中有至少兩個人生日相同的機率為 0.509
,即 50.9%
,超過一半的可能性。
通過公式可以看到,隨著房間中人數的增加,至少有兩人生日相同的機率也增加。例如,一個教室有 30 名學生,那麼兩個同學生日相同的機率為 70%。如果把人數增加到 70 個人,那麼至少有兩人生日是同一天的機率為 99.9%。
延伸閱讀:
閱讀 你所不知道的C語言: linked list 和非連續記憶體操作 共筆和觀看解說錄影。
$ git clone https://github.com/sysprog21/linux-list
$ cd linux-list
$ make
預期會得到以下輸出:
CC tests/containerof.o
LD tests/containerof
*** Validating tests/containerof ***
[ Verified ]
...
CC tests/list_cut_position.o
LD tests/list_cut_position
*** Validating tests/list\_cut\_position ***
[ Verified ]
其中 include/list.h
學習 Linux 核心原始程式碼的 linked list 資料結構實作程式碼。
#define container_of(ptr, type, member) \
__extension__({ \
const __typeof__(((type *) 0)->member) *__pmember = (ptr); \
(type *) ((char *) __pmember - offsetof(type, member)); \
})
list.h
還定義一系列操作,為什麼呢?這些有什麼益處?LIST_POISONING
這樣的設計有何意義?list_for_each_safe
和 list_for_each
的差異在哪?"safe" 在執行時期的影響為何?@
符號,這有何意義?你能否應用在後續的程式開發呢?
tests/
目錄底下的 unit test 的作用為何?就軟體工程來說的精神為何?tests/
目錄的 unit test 可如何持續精進和改善呢?研讀 A Comparative Study Of Linked List Sorting Algorithms
examples
裡頭有兩種排序實作 (insertion 和 quick sort),請簡述其原理examples/insert-sort.c
和 examples/quick-sort.c
的實作方式,實作 merge sort,並且在 tests/
目錄提供新的 unit testinclude/list.h
的實作考量 (在上述檢查清單已提及部分)