C++ 下生成隨機數的方法有很多種,各有優缺點。
1. 利用rand()生成隨機數
這是最傳統的方法,也是在算法競賽中最廣為人知的方法。
優點:簡單、快速。
缺點:生成的隨機數“不夠好”(當然算法競賽中夠用),並且受到srand()的制約。
rand()的用法不必多說,所以重點講的是隨機種子初始化——srand()。
1.1 直接使用srand(time(0))
這也是最簡單的方法。但這有一個顯而易見的缺陷——1秒內,由於time(0)不會改變,所以生成的隨機序列完全一樣。
比如,在對拍時,你以為你風馳電掣地對拍了數十萬組數據,實際上生成的不同的數據也就幾百組而已,嚴重拖累了效率。
1.2 使用標准庫
既然time(0)不太好,換個隨機種子不就行了?並且,這個隨機種子必須變化得足夠快。
#include <sys/time.h>
timeval ti;
gettimeofday(&ti,NULL);
srand(ti.tv_usec);
其中,ti.tv_usec每微秒變化一次,已經很快了。
1.3 使用chrono (C++11)
這種就稍微麻煩一點,但比上一種方法好。
#include <chrono>
srand(chrono::duration_cast<chrono::milliseconds>(chrono::system_clock::now().time_since_epoch()).count());
2. 使用random庫(C++11)
一個十分強大的庫,限於篇幅不可能介紹完,因此選一些常用的介紹。
2.1 使用random_device (推薦)
它用法較為簡單,在Linux與Windows下均可用,生成unsigned int范圍內的整數,若要int范圍內的非負整數需要稍作轉換。(無需考慮隨機種子)(其實本質是用系統中的隨機數生成器,Linux下為/dev/(u)random,Windows為rand_s)
#include <random>
random_device rd;
unsigned int myrand_uint(){
return rd();
}
int myrand_int(){
return rd()>>1;
}
2.2 使用mt19937
循環節極長,比rand()要好,但同樣需要設置隨機種子,生成int內的整數(包括負數)。
mt19937 rd(...); //...內為隨機種子
int myrand(){
return rd();
}
3. 利用系統資源
3.1 shell的環境變量
Linux下為$RANDOM,Windows為%RANDOM%,范圍 [0,32767]。
echo $RANDOM
3.2 /dev/(u)random (Linux)
/dev/random與/dev/urandom均為塊設備文件,直接打開是一堆亂碼(其實是生成的隨機串以ASCII方式顯示),可以直接在程序中用fopen打開,用fread讀取指定字節並轉換為整數。
注意:/dev/random在生成大量隨機數時效率會降低,推薦/dev/urandom。
FILE* rd=fopen("/dev/urandom","r");
int myrand(){
unsigned int val;fread(&val,sizeof(val),1,rd);
return val>>1;
}
long long myrand_ll(){
unsigned long long val;fread(&val,sizeof(val),1,rd);
return val>>1ll;
}
完結撒花~~