C++下隨機數的生成


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;
}

完結撒花~~


免責聲明!

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



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