ToolAct工具行動

隨機抽取工具

公平隨機的抽籤、抽取、選擇工具

抽取設定
允許重複
開啟後同一選項可能被多次選中
總選項數: 0
已抽取: 0
剩餘: 0
?

什麼是隨機抽取工具?

隨機抽取工具會從候選清單中隨機選出一個結果,避免由某個人主觀決定。它適合課堂點名、會議發言順序、輕量抽獎、任務分配、午餐選擇、團隊暖身,以及任何需要用中立方式做選擇的情境。本頁支援一行一個候選項、滾動動畫、本機抽取歷史,也可以關閉重複抽取,讓已抽中的項目從剩餘池移除。隨機性可以在統計意義上減少偏向,但不會驗證身分、不會自動處理輸入中的同名項,也不能提供正式稽核證據。若用於正式抽獎、合規活動、資格核驗或獎品發放,應使用有記錄、有規則、有負責人的流程。

使用方法

操作步驟

  1. 在文字框中輸入選項,每行一個
  2. 設定要抽取的項目數量
  3. 選擇是否允許重複
  4. 點選「開始抽籤」按鈕
  5. 在右側查看結果

公平抽籤提示

  • 每行放一位候選人,移除多餘的空白行或重複項,除非刻意允許重複。
  • 公開抽籤前,請先決定種子、重複規則與重新抽籤規則,結果會更容易說明。

使用場景

從貼上的清單中抽取名稱或項目每行輸入一個項目,啟動滾動抽取動畫,使用瀏覽器 crypto 隨機數選出最終結果。最新抽中的項目會醒目顯示,每個已抽中的項目依序記錄在歷史中。每次抽取都會呼叫 crypto.getRandomValues() 於整數範圍 [0, n),因此每個剩餘名稱都有精確的 1/n 機率,且選中的索引在動畫開始前就已確定,這意味著重新執行相同動畫會落在同一個得獎者身上。
執行重複或不重複的抽取切換項目是否可被重複選中。在不重複模式下,已抽中的項目會從可用池中移除並顯示剩餘數量,適合抽獎、課堂輪流、家務分配和團隊分組。兩種模式有不同的公平性特性:不重複保證覆蓋,重複抽取則在每次旋轉中保持相等機率,可以合理地連續兩次抽中同一個名稱。選擇符合你向現場宣布的規則的模式。
重新整理頁面後保留抽取狀態輸入清單和抽取記錄會儲存到 localStorage,因此即使意外重新整理也不會丟失。結果可作為有序列表複製,或在新一輪開始時單獨清除而不影響來源清單。使用專門的「清除記錄」按鈕可抹除歷史以便開始新活動,同時保留候選清單,因為兩者儲存在不同的鍵下,清除其中一個不會影響另一個。
使用計數器執行有序的課堂輪流切換到不重複模式,讀取抽取歷史追蹤哪些學生已經回答過,因此下一次抽中的一定是還沒發言的人。結果下方的剩餘計數讓你輕鬆看出一輪何時接近尾尾聲,讓老師可以調整最後幾個問題的節奏,而不是用完所有名稱。暖身快速抽選練習可重置為重複模式,重複在這種場景中是可以接受的。
匯出小型抽獎的可稽核得獎名單將抽取歷史複製為有序列表,讓小型團隊贈品有每個選擇的帶時間戳記錄。附上來源清單、抽取規則和抽取畫面的截圖,因為 localStorage 是每個瀏覽器和每個裝置獨立的,不是持久的記錄系統。對於付費抽獎、受監管的抽籤或合規敏感的活動,請在專為稽核和見證設計的系統中執行抽取,而非僅在瀏覽器頁面上進行。

技術原理

隨機抽取工具基於 Web Crypto API(W3C、WHATWG),具體使用的是 crypto.getRandomValues(typedArray),這是瀏覽器中唯一暴露的加密安全隨機數來源。底層瀏覽器會呼叫作業系統的 CSPRNG:Windows 上的 CryptGenRandom(Windows 10 起使用 AES-256 CTR-DRBG 模式)、Linux 上的 getrandom(2)(讀取與內核 /dev/urandom 相同的 ChaCha20 池)、macOS 上的 SecRandomCopyBytes,以及 iOS、Android 和 BSD 上的對應實作。其輸出適用於金鑰生成、隨機數、鹽值、初始化向量,以及任何可預測性會造成安全問題的場景。 「加密等級」的區別很重要。V8 中的 Math.random() 使用 xorshift128+(一種快速、低熵的演算法),回傳 [0, 1) 範圍內的 64 位元浮點數;惡意觀察者在理論上只需觀測少量輸出就能重建 128 位元狀態並預測所有未來值。SpiderMonkey 和 JavaScriptCore 的情況也類似。這使得 Math.random() 不適用於任何結果必須不可猜測的場景——公平的中獎者選擇、權杖、一次性密碼、紙牌遊戲中的交易、稽核抽樣。crypto.getRandomValues(typedArray) 是這些場景的唯一選擇。 將均勻分佈的 32 位元整數映射到 [0, N) 範圍內的均勻索引且無模偏差,是區分正確與錯誤實作的第二個工程細節。直接用 idx = randomUint32 % N 是錯誤的:若 N 不能整除 2 的 32 次方,前 2 的 32 次方 mod N 個值的出現機率會略高。正確的演算法是拒絕取樣:計算 limit = 2 的 32 次方 - (2 的 32 次方 mod N);抽取 32 位元值 r;若 r >= limit 則重新抽取;否則回傳 r % N。偏差從 O(N / 2 的 32 次方) 降至零。對於 N = 2 或 N 為 2 的冪次方,取模是精確的,但拒絕取樣是安全的預設方案,平均最多只需一次重抽(且保證終止)。 抽取工具將結果以帶版本號的鍵存入 localStorage,因此工作階段可在頁面重新載入後存活,使用者也能回顧抽取歷史。歷史記錄未加密或簽署——它是本機的、非敏感的,且容易清除。在不重複模式下,演算法使用 Fisher-Yates 部分洗牌進行無放回抽取:在 N 步中的第 k 步,將第 k 個元素與 [k, N) 範圍內均勻選取的元素交換,並將第 k 個元素鎖定為已抽取。這是 O(N) 時間、O(1) 額外空間,且每種排列的概率相等,這是正確的組合保證。(「抽 N 次並拒絕重複」的方式也是正確的,但最壞情況下為 O(N²),在長清單上可能卡住。) 對於加權抽取(每個選項有各自的機率),標準演算法是前綴和陣列的反 CDF 取樣:建立權重的前綴和,抽取 [0, 總和) 範圍內的均勻實數,然後二分搜尋最小的 i 使得 prefix[i] >= u。每次抽取為 O(log N),前綴和在每次變更時建立一次。Alias 方法(Walker-Vose)可在 O(1) 時間內完成每次抽取,代價是 O(N) 的初始化,僅在 N 很大且分佈固定時才有價值。

  • 隨機數來源:crypto.getRandomValues(typedArray) — 瀏覽器中唯一的加密安全 RNG,由作業系統層級的 CSPRNG 支援(Windows 10+ 使用 AES-256 CTR-DRBG、Linux/macOS/iOS/Android 使用 ChaCha20)。
  • Math.random() 在 V8 上是 xorshift128+(其他引擎有類似變體):速度快但可預測。永遠不要用於公平抽選、權杖、一次性密碼或稽核抽樣——僅適用於視覺噪點、動畫或非安全取樣。
  • 無偏差索引映射:拒絕取樣,而非取模。計算 limit = 2³² - (2³² mod N);若隨機的 uint32 >= limit 則重新抽取;否則回傳 r % N。避免了經典的「模偏差」問題,即較小範圍的索引出現頻率更高。
  • 不重複抽取使用 Fisher-Yates 部分洗牌,O(N) 時間、O(1) 空間:在第 k 步將第 k 個元素與 [k, N) 中的均勻元素交換,然後鎖定 k。每種排列概率相等。
  • 加權抽取使用反 CDF 取樣:一次性建立權重的前綴和,抽取 [0, 總和) 範圍內的均勻實數,二分搜尋最小的 prefix[i] >= u。每次抽取 O(log N)。
  • 抽取歷史以帶版本號的鍵存入 localStorage,工作階段可在頁面重新載入後存活。歷史記錄僅存於本機且非安全敏感——使用完畢後從介面清除即可。
  • Fisher-Yates 與「拒絕重複抽 N 次」的比較:兩者在分佈上都正確,但 Fisher-Yates 總計 O(N) 時間、O(1) 空間,而朴素拒絕法在最壞情況下為 O(N²)(長清單末尾大量重複)。
  • 輸出範圍與類型:getRandomValues 接受 Int8Array、Uint8Array、Int16Array、Uint16Array、Int32Array、Uint32Array、BigInt64Array、BigUint64Array — 頁面始終使用 Uint32Array 作為索引映射步驟的輸入。

範例

從候選清單不重複抽選

輸入清單(每行一個):
  Alice
  Bob
  Charlie
  David
  Eve
  Frank

允許重複:關閉    抽選數:3
結果:
  #1: Charlie
  #2: Alice
  #3: Frank
  (Bob、David、Eve 仍留在候選池中)

頁面對 Uint32Array 呼叫 crypto.getRandomValues(),為每次抽選
產生 [0, n) 範圍內的均勻整數,n 為剩餘候選人數。每個名字在
每次抽選都有相同的 1/n 機率,且選中的索引在動畫開始前就
已固定。

允許重複並附時間戳記錄的抽選

輸入清單(每行一個):
  Head
  Tails

允許重複:開啟    抽選數:5
結果:
  #1 (14:23:01): Head
  #2 (14:23:01): Tails
  #3 (14:23:01): Head
  #4 (14:23:01): Head
  #5 (14:23:01): Tails

在重複模式下,同一項目可連續被抽中,候選池也不會縮小。
每筆紀錄都會加上抽選時間戳,因此同一份候選清單可在多輪
中重複使用,而歷史紀錄能精確顯示每次抽選發生的時間。
清除紀錄與清除候選清單為獨立操作 — 兩者儲存在不同的
localStorage 鍵下。

底層選取邏輯的 JavaScript 片段

// 使用 Web Crypto (CSPRNG) 從 [0, n) 中挑一個索引
function pickIndex(n) {
  // crypto.getRandomValues 提供均勻的 32 位元值;此處對 n 取模
  // 是安全的,因為清單抽選的 n 最多只有數千,2^32 / n 很大,
  // 因此模偏差可忽略不計。
  const buf = new Uint32Array(1);
  crypto.getRandomValues(buf);
  return buf[0] % n;
}

// pickIndex(6) -> 例如 4   (上方範例中的 Charlie)
// pickIndex(2) -> 0 或 1   (Head 或 Tails)
//
// 注意:當候選池極大、n 接近 2^32 時,請改用拒絕取樣以消除
// 模偏差,例如:
//   const limit = Math.floor(0xFFFFFFFF / n) * n;
//   let r; do { crypto.getRandomValues(buf); r = buf[0]; } while (r >= limit);

1,000 次抽選的公平性檢查

清單:     ['A', 'B', 'C', 'D']    (4 個項目,預期占比 25.0%)
抽選數:    1,000    允許重複:開啟
實測:
  A: 247    (24.7%)
  B: 256    (25.6%)
  C: 248    (24.8%)
  D: 249    (24.9%)

使用 crypto.getRandomValues 進行 1,000 次抽選時,每個項目
應落在預期占比的 +/- 3 個百分點內;若偏差較大(例如某項
達 35%),通常代表實作呼叫了 Math.random() 或取模方式有誤。
對於受監管的抽獎活動,請儲存原始候選清單、亂數種子來源
(瀏覽器/作業系統熵)、抽選時間戳與見證簽章 — localStorage
並非可長期信賴的紀錄系統。

常見問題

抽選結果真的是隨機的嗎?

是的。抽選使用 Web Crypto API 的 crypto.getRandomValues,具備密碼學等級強度。除非你設定權重,否則每個選項的中獎機率完全相等。

同一個選項會連續被抽中兩次嗎?

會,獨立隨機抽選本來就是這樣。例如有 5 個選項時,連續兩次抽到同一個的機率是 1/5 = 20%。如果不希望重複,可以開啟「抽中後移除」,這樣會以不放回的方式抽選,直到清單抽空為止。

「一次抽 N 個」是怎麼處理的?

預設採用不放回抽樣,每個項目在這一輪 N 個的抽選中最多只會被抽到一次。如果可以接受重複(例如指派 N 件任務給同一個人),可切換為「放回抽樣」。在不放回模式下,N 不能大於選項清單的數量。

可以加入權重來調整中獎機率嗎?

部分版本支援為每個選項設定權重(例如 A 權重 3、B 權重 1,A 中獎機率為 B 的 3 倍)。頁面會將權重歸一化為機率。若沒有設定權重,所有選項機率相等。

為什麼比起「憑直覺挑」更公平?

人類其實很不擅長隨機,傾向避開最近選過的、過度偏向顯眼選項,也會無意識地偏向熟悉的名字。由電腦來抽就能消除這些偏差,對抽獎類決定來說,參與者也會覺得更乾淨俐落。

我的清單會被儲存嗎?

部分版本會存到 localStorage,所以同一個瀏覽器中清單會被保留。關閉分頁或切換瀏覽器後就會遺失,除非你先匯出。所有資料都不會上傳。

可以拿來做合法的抽獎嗎?

不建議。合法的抽獎、樂透與博弈開獎都需要可稽核的隨機程序,常常需要實體裝置或經過認證的 RNG 硬體。一般網頁工具沒有相關文件與審計,建議只用於辦公室抽獎與非正式抽選。