前 9 篇在這裡:
- 《C++11 新特性之新型別與初始化》
- 《C++11 新特性之型別推斷與型別獲取》
- 《C++11 新特性之 lambda》
- 《C++11 新特性之容器相關特性》
- 《C++11 新特性之智慧指標》
- 《C++11 新特性之 Class》
- 《C++ 11 新特性之右值引用與移動》
- 《C++ 11 新特性之 template》
- 《C++ 11 新特性之正規表示式》
這是C++11新特性介紹的第十部分,涉及到隨機數庫相關的新特性。
不想看toy code的讀者可以直接拉到文章最後看這部分的總結。
簡介
之前,C++中的隨機數生成都依賴於一個簡單的rand函式。這個函式產生一定範圍內的一個均勻隨機整數。如果需要其他隨機分佈或者其他範圍的隨機數,就需要根據rand函式產生的隨機數進行再加工,不過這時,就容易引入非隨機性了。
C++11新標準中引入了一個新的隨機數庫,相關功能定義在random標頭檔案中,通過多個互相協作的類,可以生成任意範圍內、服從多種隨機分佈的隨機數。
隨機引擎
新的隨機數庫中引入了隨機引擎的概念。一個隨機引擎將產生一組原始的隨機數列,一般這些原始的隨機數不能直接使用,要配合隨機分佈類產生符合某分佈的隨機數後才能進行使用。
一般,最常用的隨機引擎是default_random_engine。
1 2 3 4 5 6 7 |
std::cout<<"test default random engine:\n"; std::default_random_engine e; e.seed(time(0)); for(size_t i = 0; i < 10; i++) std::cout<<e()<<'\t'; std::cout<<'\n'; std::cout<<"test default random engine done.\n"<<std::endl; |
隨機分佈
可以用uniform_int_distribution和隨機引擎配合來產生均勻分佈的隨機整數。
1 2 3 4 5 6 7 |
std::cout<<"test random distribution:\n"; e.seed(time(0)); std::uniform_int_distribution<unsigned> u(0, 9); for(size_t i = 0; i < 10; i++) std::cout<<u(e)<<'\t'; std::cout<<'\n'; std::cout<<"test random distribution done.\n"<<std::endl; |
類似的,uniform_real_distribution則可以產生一個均勻分佈的實數。
1 2 3 4 5 6 7 |
std::cout<<"test real distribution:\n"; e.seed(time(0)); std::uniform_real_distribution<double> u2(0, 1); for(size_t i = 0; i < 10; i++) std::cout<<u2(e)<<'\t'; std::cout<<'\n'; std::cout<<"test real distribution done.\n"<<std::endl; |
換一個分佈,試試正態分佈:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
std::cout<<"test normal distribution:\n"; e.seed(time(0)); std::normal_distribution<> n(4, 1.5); std::vector<unsigned> vals(9); for(size_t i = 0; i < 250; i++) { unsigned v = lround(n(e)); if(v < vals.size()) vals[v]++; } for(size_t i = 0; i < vals.size(); i++) { std::cout<<i<<": "<<std::string(vals[i], '*')<<std::endl; } std::cout<<"test normal distribution done.\n"<<std::endl; |
伯努利分佈也是經常會使用到的:
1 2 3 4 5 6 7 8 9 10 11 12 |
std::cout<<"test bernoulli distribution:\n"; e.seed(time(0)); std::bernoulli_distribution b(0.7); std::vector<unsigned> bers(2); for(size_t i = 0; i < 200; i++) { if(b(e)) bers[1]++; else bers[0]++; } std::cout<<"True: "<<bers[1]<<std::endl; std::cout<<"False: "<<bers[0]<<std::endl; std::cout<<"test bernoulli distribution done.\n"; |
輸出
整個測試程式的輸出結果如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
test default random engine: 1446291605 455604842 1571377939 395129967 929918845 1907528696 51427609 1055398369 2012947210 146383632 test default random engine done. test random distribution: 6 2 7 1 4 8 0 4 9 0 test random distribution done. test real distribution: 0.212158 0.183997 0.888262 0.491458 0.0681652 0.173643 0.128234 0.954471 0.891836 0.912416 test real distribution done. test normal distribution: 0: ** 1: ******** 2: ****************************** 3: ************************************************* 4: ***************************************************************** 5: ******************************************************* 6: ***************************** 7: ********* 8: * test normal distribution done. test bernoulli distribution: True: 132 False: 68 test bernoulli distribution done. |
總結
- C++11新標準中引入了比rand更強大的隨機數庫。
- 隨機數引擎和隨機分佈類配合,共同產生符合某一分佈、在某一範圍內的隨機數。
完整程式碼詳見random.cpp
打賞支援我寫出更多好文章,謝謝!
打賞作者
打賞支援我寫出更多好文章,謝謝!
任選一種支付方式