C 11隨機數發生器 VS rand

2021-07-04 00:19:33 字數 4677 閱讀 7220

舊式的隨機數發生器沿用c的rand()函式,這個函式會產生區間在[0,rand_max]的偽隨機數,且隨機數近似可以看做符合均勻分布。

傳統做法的弊端大致有兩個:

1、經常需要做人肉變換隨機數產生區間,且人肉變換過程中極易破壞原有的分布性質;

2、難以產生符合制定分布的隨機數;

rand()函式的一些問題:

很多程式需要不同範圍的隨機數;

一些應用需要隨機浮點數;

一些程式需要非均勻分布的數;

而程式設計師為了解決這些問題而試圖轉換rand生成的隨機數的範圍、型別或分布時,常常會引入非隨機性。

一、c++ 11新標準針對這兩點做了很大的改進——隨機數發生器(定義在標頭檔案random)。

新設施利用兩部分來生成隨機數:

(1)、random number engines(引擎類):負責生成原始隨機數

(2)、random number distributions(分布類): 迫使生成的隨機數在統計上滿足指定的概率分布

stl預先指定了一系列的生成引擎,並且提供乙個default_random_engine。default_random_engine會使用某個預定義的引擎,且不同編譯器、不同平台的實現可能不同。

ps:有關詳細的預定義引擎及分布類列表:

例子1:

std::default_random_engine e;

for (size_t i = 0; i < 10; i++)

預設情況下,引擎產生的隨機數範圍在default_randm_engine::min和default_random_engine::max之間。

例子2:

可以指定隨機數要符合的分布性質,例如說,在[5,20]上的均勻分布。

std::default_random_engine e;

std::uniform_int_distribution<> u(5,20);

for (size_t i = 0; i < 10; i++)

注意:我們傳遞給分布物件的是引擎物件本身,即u(e)。我們傳遞的是引擎本身,而不是它生成的下乙個值,原因是某些分布可能需要呼叫引擎多次才能產生乙個值。如果我們將呼叫寫成u(e()),含義就變為將e生成的下乙個值傳遞給u,這將會導致乙個編譯錯誤。

//int rand_num = rand()%11;//rand獲取0-10隨機數的方法

//default_random_engine也同樣可以指定隨機數範圍,那就是它的好**分布型別:uniform_int_distribution

uniform_int_distributionu(0,10);//生成0到10(包含)均勻分布的隨機數

default_random_engine e;//生成隨機無符號數

for(int i=0;i<10;++i)

例子3:

關於種子。

std::default_random_engine e(time(nullptr));

std::uniform_int_distribution<> u(5,20);

}

不過,由於time的精度是秒,所以在某些極端情況下,這也並不是乙個非常好的選擇。另外,如果程式作為乙個自動過程的一部分反覆執行,將time的返回值作為種子的方式就無效了,它可能多次使用的相同的種子。

幸運的,c++11提供了乙個非常友好的類:random_device。這個類的作用是,可以產生non-deterministic random numbers.

這個類有可能產生真正的隨機數,不過真是效果和具體實現有關。某些平台可能才用偽隨機數作為底層實現也說不定呢…

顯然的,我們可以利用random_device去初始化我們的隨機數種子

std::random_device rd;

std::default_random_engine e(rd());

std::uniform_int_distribution<> u(5,20);

for (size_t i = 0; i < 10; i++)

例子4:

為引擎設定種子的方式有兩種,一種是建立時初始化種子,另一種是呼叫seed來初始化。

default_random_engine e1;		//使用預設的種子

default_random_engine e2(2300); //使用給定的種子

default_random_engine e3;

e3.seed(2300); //e3使用的種子與e2是一樣一樣的。

三、生成隨機浮點數。

程式需要0到1之間的隨機數。

最常用但是不正確的做法:從rand獲得乙個隨機浮點數的方法是用rand()的結果除以radn_max——即系統定義的rand可以生成的最大隨機數的上界。——這種方法不正確的原因是:隨機整數的精度通常低於隨機浮點數,這樣,有一些浮點數就永遠不會生成了!

使用c++11的隨機數發生器,可以讓標準庫來處理從隨機整數到隨機浮點數的對映。

void main()

}

四、生成非均勻分布的隨機數

比如伯努利分布、正態分佈、抽樣分布、泊松分布等。

例子:生成乙個正態分佈的值序列,並畫出值的分布。

int main()

int sum = accumulate(vals.begin(), vals.end(), 0);

if (sum != 200)

cout << "discarded " << 200 - sum << " results" << endl;

for (size_t j = 0; j != vals.size(); ++j)

cout << j << ": " << string(vals[j], '*') << endl;//列印乙個由*組成的string

return 0;

}

特別注意:乙個給定的隨機數發生器一直會產生相同的隨機數序列。乙個函式如果定義了區域性的隨機數發生器,應該將其(引擎物件+分布物件)定義為static的。否則,每次呼叫函式都會生成相同的序列。

#include#include#includeusing namespace std;

/*vectorbad_rand()

return vec;

}void main()

vectorv2(bad_rand());

for (size_t k = 0; k < 10; k++)

cout << ((v1 == v2) ? "equal" : "not equal" )<< endl;//列印「equal」!

//v1 : 2

//v1 : 2

//v1 : 4

//v1 : 5

//v1 : 4

//v1 : 1

//v1 : 9

//v1 : 5

//v1 : 8

//v1 : 3

//v2 : 2

//v2 : 2

//v2 : 4

//v2 : 5

//v2 : 4

//v2 : 1

//v2 : 9

//v2 : 5

//v2 : 8

//v2 : 3

//equal

//隨機數發生器此特性會使新手迷惑:即使生成的書看起來是隨機的,但對乙個給定的發生器,每次執行程式它都會返回相同的數值串行。

//序列不變這一事實在除錯時非常有用。但是另外一方面,使用隨機數發生器的程式也必須注意這一點。

}*/

//解決上述問題的辦法:

vectorgood_rand()

return vec;

}void main()

vectorv2(good_rand());

for (size_t k = 0; k < 10; k++)

cout << ((v1 == v2) ? "equal" : "not equal") << endl;//列印「not equal」!

//v1 : 2

//v1 : 2

//v1 : 4

//v1 : 5

//v1 : 4

//v1 : 1

//v1 : 9

//v1 : 5

//v1 : 8

//v1 : 3

//v2 : 5

//v2 : 5

//v2 : 0

//v2 : 6

//v2 : 9

//v2 : 0

//v2 : 9

//v2 : 4

//v2 : 7

//v2 : 6

//not equal

}

boost 隨機數發生器

在很多應用中都需要使用隨機數。本庫力求提供乙個高效的,通用的隨機數庫。boost庫有多種隨機數生成方式。先熟悉一下各種隨機數生成器的概念。數字生成器 number generator 它是乙個函式物件,沒有引數。類似於常見的rand 均勻隨機數生成器 uniform random number ge...

opencv隨機數發生器RNG

用opencv做演算法的朋友們肯定為隨機數煩惱過,新版本一直支援隨機數產生器啦,而且還繼續支援之前版本的c格式的函式,不過與時俱進,我這裡介紹c 的rng類。它可以壓縮乙個64位的i整數並可以得到scalar和array的隨機數。目前的版本支援均勻分布隨機數和gaussian分布隨機數。隨機數的產生...

產生隨意隨機數發生器

怎樣利用給定的隨機數發生器產生其它隨意你想得到的隨機數發生器。假定給定的隨機數發生器是變數產生離散變數x 服從某一分布 比如均勻分布。高斯分布等等 隨意你想得到的隨機數發生器滿足分布 y,如果x和 y其概率密度分布函式分布為 g x h y 假定用x 隨機數發生器產生 y隨機數發生器,以下分為2步求...