← 全部文章
數學 11 分鐘閱讀 免費

公平,藏在看不見之處

真正重要的東西,用眼睛是看不見的。——安東尼・聖修伯里《小王子》

Horris Tse
Horris Tse HtPi 創辦人
收藏

一副牌有沒有洗均勻,我們通常用眼睛判斷。原本相連的牌被拆散了,紅黑交錯,數字看起來似乎無規律便算洗好了。

但公平與否,恰好深藏在看得見的假像後面。同樣要打亂 52 張牌,交叉洗牌最少要七次,過手洗牌可能要上千次;電腦剛剛好要 51 次。為甚麼答案可以相差這麼遠?背後的原因,用心才看得見。

牌局開始前,總有人拿起整副牌,熟練地分成兩疊,讓牌角交錯落下。唰的一聲,原本整齊的牌序散開了。再洗兩三次,肉眼已經看不出規律;桌上的人通常也不會要求驗證。

但看不出規律,不代表規律已經消失。一副牌可以看起來很亂,原來的先後次序卻仍藏在裏面;某些牌序比較容易出現,另一些則幾乎沒有機會。

這不是紙牌有記憶。只是每種洗法都有自己的動作規則,而規則會限制每張牌能走到哪裏。只要限制仍在,上一個次序留下的痕跡便沒有真正消失。

52! ≈ 8.07 × 1067

52 張各不相同的牌,共有這麼多種排列。

所謂「公平地洗牌」,不只是讓人猜不到下一張牌。更嚴格的意思是:在這 52! 種牌序之中,每一種都應該有相同機會出現。

人手洗牌只能靠一次又一次動作,慢慢磨走原來的次序。電腦面對同一個目標,卻毋須沿用同一種方法。

牌已經散開,原序卻還未消失

先看最常見的交叉洗牌(riffle shuffle):把牌大約分成兩半,再讓兩疊牌交錯落下。

表面上,牌的位置大幅改變了;但每一半內部的先後次序,大致仍然保留。假設原本是 1 至 52,洗一次之後,我們往往仍能在新牌序裡找到兩條向上延續的序列。數學家稱它們為 rising sequences。再洗一次,最多變成四條;再一次,最多八條。每次洗牌都在拆散舊次序,但不是把它一筆抹去。

1992 年,Dave Bayer 與 Persi Diaconis 把這種洗法寫成精確模型,再量度洗完後的牌序與真正均勻隨機相差多遠。結果不是一條平滑的斜線:洗到第五次,差距仍然很大;由第六次到第七次,才出現明顯躍升。這種突然跨過臨界位置的現象,叫做 cutoff

所以流傳最廣的答案是:52 張牌,交叉洗牌最少要七次才夠亂。

七次之後,就是完全隨機嗎?

不是。Bayer–Diaconis 的表中,六次交叉洗牌與均勻分布的 total variation distance 約為 0.614;七次降至 0.334,八次再降至 0.167。第七次之所以重要,是因為它跨過主要的陡降位置,而不是因為數學在第七次蓋了一個「合格」印章。

而且這個結論建基於 Gilbert–Shannon–Reeds 模型:切牌位置服從特定分布,兩疊牌亦按剩餘張數的比例交錯落下。真實世界有人洗得好,有人洗得像把兩疊牌疊回一起;「七次」不是對任何手勢都適用的保證。

同樣是洗牌,答案可以相差上百倍

如果你不懂交叉洗牌,可能會用過手洗牌(overhand shuffle):從手上的牌中抽出一小疊放到另一隻手,再放回剩餘那疊牌的上或下方。它看來也有切、有移、有重組,問題是許多相鄰的牌會整組留下。牌序被翻動了,卻拆得很慢。

Robin Pemantle 在 1989 年分析一個過手洗牌模型。對 52 張牌,他得到的數值證據是:要進入較接近均勻隨機的範圍,可能需要 1,000 至 3,000 次。這不是說你每晚打牌前真的要洗足三千次;它說明的是,兩種看似同類的動作,混合效率可以完全不同。

還有另一種做法是把牌全部攤在桌上,用雙手來回推散,也就是常說的 wash。它能同時打散大量相鄰關係,效果往往很好;代價也很直觀:佔地方、費時間,最後還要把 52 張牌逐一收回來。

看起來夠亂,和每種結果都同樣可能,是兩回事。

一副牌看來橫七豎八,不代表每種牌序都機會均等。反過來,一個沒有紙牌翻飛、甚至只重複 51 個簡單步驟的程序,卻可以把公平寫進結構裡。

在電腦上,應該模擬哪一種洗法?

假設現在不是在牌桌,而是在寫一個線上遊戲。畫面裡有 52 張牌,也需要在開局前洗牌。最自然的問題似乎是:程式應該模擬交叉洗牌、過手洗牌,還是把牌攤開來 wash?

但電腦沒有手,沒有紙牌的摩擦力,也沒有一張必須收拾的桌面。把這些全部模擬出來,當然可以;只是如果目的純粹是得到公平的新牌序,那些細節並不是問題重點。

這裏藏着一個容易忽略的分別:模擬人手怎樣洗牌,是一個問題;產生一副公平的新牌序,是另一個問題。

Fisher–Yates 洗牌法解決的正是後者。

不模仿雙手,直接處理牌序

想像 52 張牌排在 52 個位置。先處理最後一張:從全部 52 張牌中隨機選一張(包括自己),跟這一張交換。最後一張就此確定,不再換位。

接下來,處理倒數第二張:從餘下 51 張之中隨機選一張交換。再來是 50 張、49 張……一路縮小選擇範圍,直到只剩第一張。

for i from 51 down to 1:
    j = random integer from 0 to i
    swap(deck[i], deck[j])

52 張牌只需 51 個步驟。若某一步剛好抽中自己,兩張不同的牌甚至不必真的交換;所以準確來說,是 51 次隨機選擇,不一定是 51 次實質對調。

它為甚麼公平?看第一步便知道:每一張牌進入最後一格的機會都是 1/52。最後一格確定後,每一張餘下的牌進入倒數第二格的條件機會都是 1/51。如此下去,任何一個指定牌序出現的機會都是:

1/52 × 1/51 × … × 1/2 = 1/52!

沒有哪一種牌序多拿一張彩票。只要每次隨機選擇本身公平,最後所有排列便等機會出現。

這方法真的是 Fisher 和 Yates 原本設計的樣子嗎?

概念源自 Ronald Fisher 與 Frank Yates 1938 年的統計表:當時沒有一行程式可以呼叫亂數,他們以隨機數字表逐項抽取尚未選過的項目。1964 年,Richard Durstenfeld 把方法改寫成今天常見的原地交換版本;後來 Donald Knuth 令它在程式設計界更普及。

因此今天說的「Fisher–Yates shuffle」,通常指這個由後往前、逐步縮小範圍的版本;也有人稱它為 Knuth shuffle。

看起來很隨機,仍然可以不公平

Fisher–Yates 的程式短得讓人很想自行改寫。最常見的一個錯誤,是逐張牌處理,但每次都從整副 52 張牌中任選一張交換。它確實會把牌弄得很亂;問題是,不同牌序擁有不同數目的抵達路徑。

有一個不必逐項計算的破綻:這個做法有 5252 條可能路徑,但要平均分給 52! 種牌序。前者不能被後者整除,因此不可能每種牌序都分得一樣多。外表蒙混過了,算術卻露出破綻。

還有另一個常見捷徑:不寫洗牌程序,直接叫程式把整副牌「隨機排序」。以下一行程式的意思是,每當排序器拿起兩張牌比較,程式都臨時拋一次硬幣,隨機回答哪一張應該排在前面:

deck.sort(() => Math.random() - 0.5)

問題是,排序器不是把所有牌一次過隨機灑開;它會反覆比較不同牌,再根據先前的答案逐步調整位置。正常排序時,答案必須前後相容:如果它先得知 A 應排在 B 前、B 應排在 C 前,之後便不能又收到 C 應排在 A 前的答案。上面的程式每次都重新抽籤,同一對牌再次比較時也可能得到相反結果。排序器於是拿着一組互相衝突的指示工作;最後哪些牌序較常出現,便取決於瀏覽器實際採用哪一套排序步驟,而不會自然變成六種、甚至 52! 種牌序機會均等。

這也是為甚麼 Fisher–Yates 比模擬人手洗牌更適合一般電腦程式。並不是因為它比較像真正洗牌;恰好相反,它把不必要的物理細節全部拿走,只保留我們真正需要的東西:從所有排列中公平地抽出一個。

執行它的時間跟牌的數目只有線性關係;而且每一步的行為可以逐項清楚查驗;公平與否也能由結構直接證明。若硬要模擬交叉洗牌,我們還要決定切牌有多準、每張牌落下的機率、手勢是否每次相同。模型愈像現實,未必愈接近目的。

不過,演算法公平不等於整個系統必然公平。Fisher–Yates 假設每一步取得的隨機整數本身沒有偏差。普通偽亂數足以應付不少遊戲;牽涉金錢、安全或可驗證公平時,亂數來源、種子、取樣方式與審計機制都要另外處理。好的洗牌演算法,救不了一個壞的亂數來源。

真正要保留的,不是洗牌動作

現實世界不只把問題交給我們,也常常順手附上一套熟悉的解法。人手洗牌靠切、疊、推、碰撞;當紙牌走進電腦,我們便很自然地想把這串動作一併搬進去。

但一副牌的「公平」,並不藏在手勢裡。它藏在所有牌序的機會是否相同。

看清這一點,問題就變了:我們不再問電腦如何像人一樣洗牌,而是問,怎樣直接生成一個公平的排列。Fisher–Yates 沒有把現實模擬得更仔細;它只是把問題看得更準。

這種取捨不只出現在紙牌。橋樑承重分析必須保留材料、結構與受力;網上抽獎卻毋須模擬紙條在箱內如何翻滾,只要每個號碼被抽中的機會相同。模型應該留下多少現實,不由細節多寡決定,而要看哪些細節真的會改變答案。

最好的模型,不是保留最多現實;
而是沒有刪掉任何重要的東西。

下一次看到電腦把一副牌洗開,畫面可以有紙牌翻飛,也可以有清脆的洗牌聲。那是設計,是氣氛,是我們熟悉的隱喻。

真正令牌局公平的,可能只是背景裡那 51 步。

資料與延伸閱讀

  1. Dave Bayer & Persi Diaconis, “Trailing the Dovetail Shuffle to Its Lair”, The Annals of Applied Probability, 1992.
  2. Robin Pemantle, “Randomization Time for the Overhand Shuffle”, Journal of Theoretical Probability, 1989.
  3. Ronald A. Fisher & Frank Yates, Statistical Tables for Biological, Agricultural and Medical Research, 1938.
  4. Evi Kordon, “The Fisher–Yates shuffle”, Archive of Formal Proofs, 2026.
來自實驗室

喜歡這篇?

訂閱以收到實驗室的新文章,以及不時的課堂邀請。設有免費與付費方案——依你想要的深度閱讀。

訂閱——免費與付費
繼續閱讀
公司還不知道值多少,錢卻先進來了
金融 12 分鐘
有些聲音,消失了也不會被發現
數據 × 行為 12 分鐘
AI 前傳|讓編碼變成可能的兩位傳奇人物 · 下篇 · 圖靈
AI 13 分鐘
← 全部文章 海納百川,自乘一派