C++線性同餘法生成亂數(linear_congruential_engine)用法詳解

2020-07-16 10:04:29
linear_congruential_engine 類別範本實現了一個最老且最簡單的生成整數隨機序列的演算法,它被叫作線性同餘法。這個演算法包含 3 個引數:乘數 a、增量 c 和模 m。這些值的選擇對於生成合理品質的隨機序列至關重要。這個過程需要單個的整數種子和第一個隨機值 x,x 理論上可以像這樣計算:

unsigned int x = (a*seed + c) % m;

每個亂數 xn 都可以用下面這個等式生成下一個 xn+l :

xn+1=(axn+c) modm

顯然,因為隨機值是餘數,可以生成的不同值的最大個數是 m,並且 a 和 c 的選擇不多,它所生成的值的個數會比 m 更少。然而這個演算法是簡單快速的,在髙品質的隨機序列對程式很重要時,最好選擇其他引擎範例的生成器,例如 mersenne_twister_engine。

基於線性同餘的生成器

有兩個被定義為 linear_congmential_engine 模板範例別名的亂數生成器型別:minstd_rand() 和生成 32 位無符號整數的 minstd_rand。名字來自於 “minimum standard random number generator” minstd_rand() 是 1998 年由 Stephen K.Park 和 Keith W.Miller 為生成亂數而提出的最低標準,因為那時候的生成器很少。a 被定義為 16 807,c 是 0,m 是 2 147 483 647。 m 的值是小於 232 的最大梅森素數。minstd_rand 生成器是 a 為 48271 的 minstd_rand() 的一個改進版本。

歸因於 Donald Knuth, knuth_b 亂數生成器實現了一個可以將 shuffle_order_engine 介面卡應用到 minst_rand() 生成器所產生的值上的演算法。這被描述在他的經典著作《計算機程式設計的藝術:捲2》中,並伴隨著大量的亂數生成方法和隨機性測試。通過移除連續值之間的依賴來運用介面卡增加序列的“隨機性”。

這些生成器(事實上所有的生成器)的使用方式都和前面看到的 default_random_ engine 相同,例如:
std::random_device rd;
std::minstd_rand rng {rd()};
std::uniform_int_distribution<long> dist {-5L, 5L};
for(size_t i{}; i < 8; ++i)
std::cout << std::setw (2) << dist (rng) <<" "; // 3 -5 -2 4 -5 4 1 0