C++中隨機數的生成

1.隨機數由生成器和分佈器結合產生

生成器generator:可以產生離散的等可能分佈數值
分佈器distributions: 可以把generator產生的均勻分佈值映射到其餘常見分佈,如均勻分佈uniform,正態分佈normal,二項分佈binomial,泊松分佈poisson

2.分佈器利用運算符()產生隨機數,要傳入一個generator對象做爲參數

1 std::default_random_engine generator;  
2 std::uniform_int_distribution<int> dis(0,100);  
3 for(int i=0;i<5;i++)  
4 {  
5     std::cout<<dis(generator)<<std::endl;  
6 }

 若是嫌每次調用都要傳入generator對象麻煩,可使用std::bind,要包含頭文件functionallinux

auto dice = std::bind(distribution,generator)之後就能夠直接調用dice()產生複合均勻分佈的隨機數。
可是屢次運行上例會發現每次產生的隨機數序列都同樣,由於沒有設定種子(同cstdlib庫中的rand和srand關係)
1 std::default_random_engine generator;  
2 std::uniform_int_distribution<int> dis(0,100);  
3 auto dice= std::bind(dis,generator);  
4 for(int i=0;i<5;i++)  
5 {  
6     std::cout<<dice()<<std::endl;  
7 }  

3.種子

        除了random_device生成器(真隨機數生成器或叫f非肯定性隨機數生成器)之外(linux中有效,windows下其實也是僞隨機),全部在庫中定義的隨機數引擎都是僞隨機數生成器,他們都利用了特定的算法實現,這些生成器都須要一個種子。種子能夠是一個數值,或者是一個帶有generate成員函數的對象。簡單的應用中,用time做種子便可。
說明:若是不設定種子,那麼產生的隨機數序列每次都同樣,如上代碼,產生5個1到6之間的隨機數,可是每次都是82 13 91 84 12
改成以下代碼,可使每次產生的隨機數序列不一樣:
1  std::default_random_engine generator(time(NULL));  
2 std::uniform_int_distribution<int> dis(0,100);  
3 auto dice= std::bind(dis,generator);  
4 for(int i=0;i<5;i++)  
5 {  
6     std::cout<<dice()<<std::endl;  
7 }  

4.關於生成器

        C++11標準提供了三個生成器模版類能夠實例化爲生成器,但須要有必定的數學功底才懂得每一個模版參數的意義,可參照算法出處的論文。
這三個生成器類模版爲:
linear_congruential_engine 線性同餘法
mersenne_twister_engine 梅森旋轉法
substract_with_carry_engine滯後Fibonacci
線性同餘法舉例
template <class UIntType, UIntType a, UIntType c, UIntType m>
class linear_congruential_engine;
第一個參數:生成器類型unsigned int,unsigned long等
第二到第四個參數:是線性同餘法公遞推公式Nj+i =(AxNj+C) (mod M)裏的三個常數值A,C,M
要求:若是m不爲0,a,c的值要小於m
如一會介紹的經常使用生成器:
1 typedef linear_congruential<unsigned long, 16807, 0, 2147483647> minstd_rand0;  
1 typedef linear_congruential<unsigned long, 48271, 0, 2147483647> minstd_rand;  
可見若是本身實例化模版類很麻煩,須要很強的數序知識,因此有幾個經常使用的幾個模版實例化生成器,他們都是須要一個種子參數就能夠:
4.1線性同餘法:
minstd_rand()
minstd_rand0
利用適配器變種後的線性同餘法
knuth_b     minstd_rand0 with shuffle_order_engine
4.2梅森旋轉法:
default_random_engine()
mt19937
mt19937_64
4.3滯後Fibonacci法
ranlux24_base
ranlux48_base
利用適配器變種後的滯後Fibonacci法:
ranlux24              ranlux24_base with discard_block_engine
ranlux48              ranlux48_base with discard_block_engine
 
三個適配器:discard_block_engine     shuffle_order_engine   independent_bits_engine

5.關於分佈器

        易知,若是隻用generator配上seed只能產生離散的等可能分佈,產生的數值在generator的min和max之間,而且結果都是UIntType的值。沒法很好的控制產生數值的分佈區間和分佈機率。若是要實現這種功能就要用到分佈器。
做用1:改變生成類型,利用模版參數
做用2:改變值區間,利用實例構造函數參數。或其響應的成員函數設置參數。
做用3:改變機率分佈,選用不一樣的分佈器類型
5.1均勻分佈:
uniform_int_distribution           整數均勻分佈
uniform_real_distribution         浮點數均勻分佈
5.2伯努利類型分佈:(僅有yes/no兩種結果,機率一個p,一個1-p)
bernoulli_distribution     伯努利分佈
binomial_distribution      二項分佈
geometry_distribution     幾何分佈
negative_biomial_distribution   負二項分佈
5.3 Rate-based distributions: 
poisson_distribution  泊松分佈
exponential_distribution 指數分佈
gamma_distribution 伽馬分佈
 weibull_distribution 威布爾分佈
extreme_value_distribution 極值分佈
5.4正態分佈相關:
normal_distribution         正態分佈
chi_squared_distribution 卡方分佈
cauchy_distribution        柯西分佈
fisher_f_distribution       費歇爾F分佈
student_t_distribution  t分佈
5.5分段分佈相關:
discrete_distribution 離散分佈
piecewise_constant_distribution 分段常數分佈
piecewise_linear_distribution 分段線性分佈
相關文章
相關標籤/搜索