在 Python 中,亂數整數通常是呼叫標準函式庫 random 模組中的 random.randint(a, b) 或 random.randrange(start, stop) 來產生,該模組建立在一個以作業系統熵作為種子的Mersenne Twister虛擬亂數產生器之上。所選範圍的兩端都會包含在內,因此像 random.randint(1, 10) 這樣的呼叫可能會回傳 1 或 10,以及介於兩者之間的任何值。當 Python 直譯器處於開啟狀態,而且目的是將該值串接到更多程式碼中時,這條程式碼路徑完全沒問題,但它並不是取得公平亂數整數的唯一路徑,也未必永遠是最快的。當真正的目的是為了抽籤、工作表、遊戲設定或快速決策而取得一個或多個無偏誤的整數時,基於瀏覽器的亂數產生器可以透過表單產生等效的輸出,無需匯入、無需安裝、無需腳本,也不需要終端機視窗。

為什麼在 Python 中產生亂數的需求經常出現
搜尋「如何在 Python 中產生亂數」通常來自下列三種工作情境之一。第一種是程式設計本身:啟動蒙地卡羅模擬、將測試資料隨機化、從清單中挑選隨機索引,或是對以 Python 清單表示的牌組進行洗牌。第二種是資料處理,其中 Jupyter notebook 或 pandas 管線需要快速的隨機抽樣或隨機排序的資料列。第三種則是日常的離線任務——挑選贏家、打破平手、選擇運動項目、挑選菜色——這些任務碰巧發生在懂 Python 的人身上,因此本能地就會想到寫程式。
在第三種情況中,Python 的解法只是達成目的的手段。實際的產出是一個數字,或一串簡短的數字清單,使用者可以將它複製到聊天視窗、試算表或留言中。對於這類任務來說,寫程式是一種負擔:你必須記住函式名稱、在 random.randint 與 random.randrange 之間做決定、開啟 REPL,然後將值複製出來。而一個接受兩個邊界與數量的表單,能將整個流程壓縮到單一畫面上。
Python 的做法:快速回顧
為了完整性,以下說明「Python 的方式」實際上是什麼樣子。標準函式庫提供 random.randint(a, b) 用於產生單一包含端點的整數,random.randrange(start, stop, step) 用於接受跨距值的半開放範圍,random.choice(seq) 用於挑選一個元素,以及 random.sample(population, k) 用於不重複地抽取元素。由種子控制的可重現性則透過 random.seed(n) 來達成。對於安全性敏感的素材(例如權杖、密碼或工作階段識別碼),應使用 secrets 模組取代 random 模組:secrets.randbelow(n) 用於產生小於 n 的非負整數,secrets.SystemRandom() 在你想要使用源自作業系統加密池的熟悉 API 時使用,而 secrets.token_hex(n) 用於產生十六進位字串。
在快速瀏覽舊教學時,有兩個事實很容易被忽略。首先,random.randint(1, 10) 和 random.randrange(1, 11) 會產生相同的結果集合,但後者更具彈性,因為它接受 step 參數,這是在 1 到 49 之間只產生奇數的唯一乾淨方式。其次,對於棘手的範圍,這兩個模組都不會憑空保證公平性:一個天真的 random.randrange(big_number) 呼叫依賴 Python 的內部機制在你使用的版本中正確處理,而初學者將其替換為 int(random.random() * big_number) 時,經常會引入微小的偏差,因為浮點數轉整數的轉換在高數值端略有不均。專門的 random 模組會在內部處理這個問題;而自製的轉換通常則無法做到。
何時基於瀏覽器的產生器更為合適
當下列任何一項成立時,基於瀏覽器的整數產生器就是正確的選擇:你手邊沒有 Python 環境可用、該值將用於程式之外(列印的清單、聊天訊息、教師大聲朗讀的數字)、你需要一次取得多個獨立的數字而偏好單次操作勝過多次呼叫,或是你正與非程式設計師一起工作,而他們需要驗證該方法。Lizely 上的亂數產生器在滿足這些條件的同時,也能保持底下的機率行為公正無偏。
具體而言,該工具從 Crypto.getRandomValues 取得資料——這是每個現行瀏覽器都支援的 W3C 標準 Web Cryptography API,它提供密碼學上強健的隨機位元組,而非僅有 32 位元狀態的虛擬亂數流。這些位元組接著透過拒絕抽樣(rejection sampling)對應到你所選的範圍,這與 Python 自家 random 模組內部用於維持均勻分布的技術相同。其結果在公平性上與妥善撰寫的 Python 呼叫無法區分,但可以從任何手機、平板或筆電上直接使用,無需任何設定,而且網頁本身僅限於瀏覽器工作階段內。
如何在不使用 Python 的情況下產生亂數
一旦了解各項控制項,端到端的流程只需片刻即可完成。
- 在瀏覽器中開啟亂數產生器。
- 在第一個欄位中輸入允許的最小整數,在第二個欄位中輸入允許的最大整數。兩個端點都是合格的結果,因此範圍 1 到 10 可能產生 1 或 10,以及介於兩者之間的任何整數。
- 輸入你需要的數字數量,介於 1 到 1,000 之間(含端點)。
- 決定是否允許重複。若重複抽出的數字應保留先前的結果,請保持允許重複;當你需要不重複的位置、識別碼或參與者編號時,請關閉重複。
- 選擇產生數字。結果會以一行以逗號分隔的形式顯示,你可以如常地反白並複製。
- 若之後變更任何輸入,先前的清單會被清除,以避免將舊結果誤認為新設定所產生的輸出。
瀏覽器中的無偏誤範圍對應如何運作
將原始的隨機位元對應到人為輸入的範圍(例如 1 到 6)是微小偏差容易出現的地方。最常見的錯誤是計算 raw % range_size + min,這會在原始範圍不是目標範圍的整數倍時,留下一段未被對應的不完整尾部。例如,四個 2 位元的原始值(0 到 3)無法平均分配到三個目標上;其中一個目標會多分配到一個輸入值,因此變得更可能出現。修正方法(在 Python 和 JavaScript 中皆有完善文件記載)是拒絕抽樣:丟棄落在不完整尾部中的值並重新抽取。Lizely 產生器完全遵循此方法,且輸入僅限於 JavaScript 安全整數,以確保包含端點的範圍大小仍能以整數表示。
隨機性本身來自 Crypto.getRandomValues,如 W3C Web Cryptography API 所定義。每個被接受的原始值對應到每個輸出整數的機率相同,因此分布對於所選範圍而言是均勻的。正是這個特性使得 secrets.randbelow 及類似的基元在 Python 中用於密碼學時可靠;底層演算法並不會因為宿主環境是瀏覽器分頁而有所不同。
在 Python 各種做法與瀏覽器工具之間做選擇
Python 生態系中的不同部分,加上基於瀏覽器的工具,各自涵蓋不同的工作。下表比較了一般讀者會遇到的方法類別。
| 方法 | 典型用途 | 隨機性的來源 | 安全性等級 |
|---|---|---|---|
| random 模組(random.randint、random.sample) | 腳本中的模擬、遊戲、洗牌、抽樣 | Mersenne Twister,由 os.urandom 提供種子 | 不適用於機密資料 |
| secrets 模組(secrets.randbelow、token_hex) | 權杖、密碼、工作階段 ID、復原碼 | 作業系統的加密池 | 密碼學等級 |
| 基於瀏覽器的亂數產生器 | 離線抽籤、決策、快速一次性使用、課堂挑選 | Web Crypto,源自 Crypto.getRandomValues | 密碼學等級的輸入,但無經簽署的稽核紀錄 |
| NumPy(np.random.randint、default_rng) | 大量陣列、統計實驗 | 預設為 PCG64;np.random 沿用舊版 MT19937 | 不適用於機密資料 |
「安全性等級」一欄反映的是熵的來源,而非對周邊流程的保證。以明碼儲存由 secrets 衍生的密碼,或使用瀏覽器熵來挑選受規範的獎項得主,仍然具有風險,因為弱點在於周邊系統而非隨機來源本身。
常見的限制與邊界情況
在開始輸入邊界之前,有幾條值得牢記的規則。
- 反向的邊界(最小值大於最大值)、空白欄位、小數值,以及超出 JavaScript 安全整數範圍的任何內容都會被拒絕。JavaScript 安全整數大約介於正負九千兆之間,這對課堂上的挑選而言綽綽有餘,但並非沒有限制。
- 若包含端點的範圍具有無法表示的大小——例如跨度為 9 秭(quintillion)的範圍——該工具會拒絕執行而非默默進位四捨五入。寬度超出安全整數範圍的值需要一個接受整數字串的系統來處理。
- 當要求的唯一值數量超過範圍所能容納的數量時,這會被視為明確錯誤,而非靜默重試:從 1 到 3 中抽出五個不重複的值是不可能的,產生器會明確指出這一點。
- 在關閉重複選項時,該工具使用稀疏的部分 Fisher-Yates 洗牌演算法,其記憶體使用量為 O(count),因此即使在包含端點的範圍很大時仍能保持回應速度。
- 關閉重複並將數量設定為等於包含端點的範圍大小,會產生該範圍的均勻隨機排列,這在座位表、報告順序或隨機決策矩陣中相當有用。
Practical Use Cases the Tool Handles Well
Classroom activities — picking a student to answer the next question, ordering presenters, randomizing seating — fit the pattern of a few unique integers drawn from a moderate range. Order selection for a small contest, where you have a numbered participant list and need five non-repeating winners, fits the unique + small count pattern. Test-data generation, where each call produces a fresh batch of integers to populate a worksheet, fits the duplicates-allowed + count = up to 1,000 pattern. Game setup — initiative order in a tabletop session, a shuffled deck index, a quick loot roll — fits both patterns depending on whether repetition is desirable.
For tasks that go beyond integers — a randomized yes or no decision, a single die roll, a choice between two contestants — dedicated single-purpose generators on Lizely handle the same range considerations without forcing you to think about safe-integer math. The Random Number Generator is the right entry point whenever the answer is genuinely "a number, or a list of numbers, in a range I specify," and the goal is to obtain it without opening a Python environment.
If you're weighing options, How to Make Random Teams in Roblox Studio covers this in detail.
If you're weighing options, How to Make a Storyline With Random Building Blocks covers this in detail.