我們知道,C 中的隨機數函數只有一個 rand( )
,想生成某一區間范圍內的隨機數乃至隨機的浮點數都十分麻煩。
而 C++11 中提供的 random
庫解決了這一問題,它能讓我們方便地生成需要的隨機值。
下面將介紹如何利用 random
庫中的組件生成符合條件的隨機數。
random
庫中的組件分為兩類——隨機數引擎類和隨機數分布類。
隨機數引擎類是可以獨立運行的隨機數發生器,它以均勻的概率生成某一類型的隨機數,但無法指定隨機數的范圍、概率等信息。因此,它也被稱為“原始隨機數發生器”,由于不能指定生成隨機數的范圍,它通常不會被單獨使用。
隨機數分布類是一個需要于隨機數引擎類的支持才能運行的類,但是它能根據用戶的需求利用隨機數引擎生成符合條件的隨機數,例如某一區間、某一分布概率的隨機數。
所有隨機數引擎類都支持的操作如下:
名稱 | 功能 |
---|---|
Engine e | 創建一個引擎。 |
Engine e(s) | 創建一個引擎,并用 s 作為種子。 |
e.seed(s) | 使用種子 s 充值 e 的狀態。 |
e.min( ), e.max( ) | e 能生成的最小值和最大值。 |
e.discard(u) | 將 e 推進 u 步(u 的類型為 unsigned long long)。 |
下表隨機數分布類共有的操作:
名稱 | 功能 |
---|---|
U u | 創建一個分布類 u 。 |
u(e) | 用隨機數引擎 e 生成隨機數(u 代表隨機數分布類)。 |
u.min( ) | u 能生成的最小值。 |
u.max( ) | u 能生成的最大值。 |
u.reset( ) | 重置 u 的狀態,使隨后 u 生成的值不受之前的值影響 。 |
隨機非負數——default_random_engine
default_random_engine
是一個隨機數引擎類。它定義的調用運算符返回一個隨機的 unsigned
類型的值。
因此,若想生成 10 個隨機非負數并輸出,程序可以這么寫:
#include <iostream>
#include <random>
using namespace std;
int main( ){
default_random_engine e;
for(int i=0; i<10; ++i)
cout<<e( )<<endl;
return 0;
}
在我們的系統中,測試結果為:
16807
282475249
1622650073
984943658
1144108930
470211272
101027544
1457850878
1458777923
2007237709
可以看出,還是比較“隨機”的。
當然,default_random_engine
也只是一個偽隨機數發生器,如果在運行一次程序,得到結果將還是這幾個數。
若想令每次運行程序時的生成結果不同,可以為其設置較為隨機的種子,比如當前系統的時間。
特定范圍的非負數——uniform_int_distribution
uniform_int_distribution
是一個隨機數分布類,也是個模板類,模板參數為生成隨機數的類型(不過只能是 int、unsigned、short、unsigned short、long、unsigned long、long long、unsigned long long 中的一種)。它的構造函數接受兩個值,表示隨機數的分布范圍(閉區間)。
因此,一個生成 0 到 9 的隨機數程序可以這么寫:
#include <iostream>
#include <random>
using namespace std;
int main( ){
default_random_engine e;
uniform_int_distribution<unsigned> u(0, 9);
for(int i=0; i<10; ++i)
cout<<u(e)<<endl;
return 0;
}
在我們的系統中,它的生成結果為:
0
1
7
4
5
2
0
6
6
9
隨機浮點數——uniform_real_distribution
uniform_real_distribution
是一個隨機數分布類,它也是模板類,參數表示隨機數類型(可選類型為 float、double、long double)。構造函數也需要最大值和最小值作為參數。
下面是一個生成 10 個 0~1 之間的隨機浮點數的例子:
#include <iostream>
#include <random>
using namespace std;
int main( ){
default_random_engine e;
uniform_real_distribution<double> u(0.0, 1.0);
for(int i=0; i<10; ++i)
cout<<u(e)<<endl;
return 0;
}
在我們的系統上的結果為:
0.131538
0.45865
0.218959
0.678865
0.934693
0.519416
0.0345721
0.5297
0.00769819
0.0668422
隨機布爾值——bernoulli_distribution
bernoulli_distribution
是一個分布類,但它不是模板類。它的構造函數只有一個參數,表示該類返回 true 的概率,該參數默認為 0.5 ,即返回 true 和 false 的概率相等。
下面是一個生成 10 個隨機布爾值的例子:
#include <iostream>
#include <random>
using namespace std;
int main( ){
default_random_engine e;
bernoulli_distribution u;
for(int i=0; i<10; ++i)
cout<<u(e)<<endl;
return 0;
}
在我們的系統上的結果為:
1
1
1
0
0
0
1
0
1
1
總結
常用的隨機數類如下:
-
default_random_engine
:隨機非負數(不建議單獨使用)。 -
uniform_int_distribution
:指定范圍的隨機非負數。 -
uniform_real_distribution
:指定范圍的隨機實數。 -
bernoulli_distribution
:指定概率的隨機布爾值。
事實上,random
庫的功能極其豐富,其中的隨機數引擎不止有 default_random_engine
一個,分布類也遠遠不止上述三個。它還能進行泊松分布、正態分布、抽樣分等高級的隨機數功能,想詳細了解這些內容請去查閱其他資料。我可能要等好久才能把這些內容補上。