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,要包含頭文件functional

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 分段線性分布


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM