HOWTO · C++

如何在 C++ 中生成一個 0 和 1 之間的隨機數

本文演示瞭如何在 0 和 1 之間建立一個區間隨機數的 C++ 方法。

本頁內容

若要產生大於或等於 0、但小於 1 的浮點偽隨機值,可將 C++11 隨機引擎與 std::uniform_real_distribution<double> 搭配使用。範例採用固定種子,因此在相同實作上使用相同引擎與種子,會重現相同的序列。新寫的 C++ 程式請使用 <random>;維護舊程式時則可沿用 std::rand。

使用 C++11 <random> 產生浮點數

引入 <random>、建立引擎,並在需要取得數值時將引擎傳給分布。引擎會產生一連串偽隨機位元;分布則將這些位元映射成指定型別與範圍的數值。這個完整範例會輸出五個數值。固定種子可讓程式在相同的標準程式庫實作上重複執行時,得到相同的結果序列。

#include <iostream>
#include <random>

int main() {
    std::mt19937 engine(2026);
    std::uniform_real_distribution<double> distribution(0.0, 1.0);

    for (int i = 0; i < 5; ++i) {
        std::cout << distribution(engine) << '\n';
    }
}

輸出的數字會因標準程式庫實作而異。在同一個實作上,使用相同的引擎與種子會從相同的序列起點開始。若要選擇另一個序列,可以使用不同的種子,或從 std::random_device 初始化引擎一次;但並非每個系統上的該裝置都能提供非決定性的熵來源。

了解輸出範圍並選擇引擎

對於 std::uniform_real_distribution<double>(0.0, 1.0),指定的區間是左閉右開:可能回傳 0,但不會回傳 1。範本引數決定浮點結果型別(float、double 或 long double)。分布需要引擎作為引數,不能單獨用來產生數值。

引擎決定偽隨機序列,種子則決定序列從何處開始。std::mt19937 是廣泛使用且演算法有明確規範的標準引擎。若不在意特定引擎,std::default_random_engine 用起來很方便;但它實際採用的引擎由實作決定,因此若需要在不同標準程式庫之間重現相同序列,就較不適合。引擎應只設定一次種子並重複使用;每次產生數值前都重新設定種子,可能造成數值重複,也會損害序列品質。這些功能適合模擬、遊戲及一般隨機化用途,但不適合產生加密密鑰等秘密資料。

僅在維護舊程式時使用 std::rand

舊程式可能會使用在 <cstdlib> 中宣告的 std::rand。它會回傳從 0 到 RAND_MAX(含)的整數。為避免整數除法,請先轉換成浮點數再進行除法。例如,行內運算式 static_cast<double>(std::rand()) / (static_cast<double>(RAND_MAX) + 1.0) 會將整數縮放到所需範圍。

這種縮放方式會讓結果小於 1,即使 std::rand 回傳 RAND_MAX 也一樣。若希望每次執行產生不同序列,請在產生數值前呼叫一次 std::srand,通常會使用與時間相關的種子;但不同次執行仍可能使用相同種子,而且設定種子不會提升產生器的品質。RAND_MAX 的值由實作決定,而 std::rand 對引擎與序列的控制能力也不如 <random>。新程式請優先使用 C++11 引擎與分布;只有在既有介面要求時,才使用這個舊式函式。