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;
minstd_rand()minstd_rand0利用適配器變種后的線性同余法knuth_b minstd_rand0 with shuffle_order_engine
default_random_engine()mt19937mt19937_64
ranlux24_baseranlux48_base
利用適配器變種后的滯后Fibonacci法:
ranlux24 ranlux24_base with discard_block_engineranlux48 ranlux48_base with discard_block_engine
作用1:改變生成類型,利用模版參數作用2:改變值區間,利用實例構造函數參數。或其響應的成員函數設置參數。作用3:改變概率分布,選用不同的分布器類型
uniform_int_distribution 整數均勻分布uniform_real_distribution 浮點數均勻分布
bernoulli_distribution 伯努利分布binomial_distribution 二項分布geometry_distribution 幾何分布negative_biomial_distribution 負二項分布
poisson_distribution 泊松分布exponential_distribution 指數分布gamma_distribution 伽馬分布weibull_distribution 威布爾分布extreme_value_distribution 極值分布
normal_distribution 正態分布chi_squared_distribution 卡方分布cauchy_distribution 柯西分布fisher_f_distribution 費歇爾F分布student_t_distribution t分布
discrete_distribution 離散分布piecewise_constant_distribution 分段常數分布piecewise_linear_distribution 分段線性分布