C 隨機數解析

2021-06-22 08:21:40 字數 2514 閱讀 2971

前幾天在做畢業設計的時候需要用到隨機數,發現隨機數並不「隨機」。rand生成的都是偽隨機數。

先來看看rand的函式原型及用法

#include

int rand( void );

功能:函式返回乙個在零到rand_max 之間的偽隨機整數。

例如:srand( time(null) );

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

printf( "random number#%d: %d\n", i, rand() );

rand_max在不同的平台下定義的大小不一樣 windows 定義的為0x7fff。

與rand()配套使用的還有另外乙個函式 srand()。

#include

void srand( unsigned seed );

功能:設定rand()

隨機序列種子。對於給定的種子seed, rand()

會反覆產生特定的隨機序列。

srand( time(null) );

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

printf( "random number#%d: %d\n", i, rand() );

解釋:srand就是為rand產生乙個初始值,若不手動呼叫srand系統也會自動呼叫srand(1),這樣每次產生的隨機數就都一樣了。程式第一次執行「隨機數」產生順序為5,8,2,5,0,1…,第二次執行仍然是5,8,2,5,0,1…,第三次執行仍然是5,8,2,5,0,1…若我們把時間做為種子的話每次生成的「隨機數」就不一樣了。

在整個程式中srand()只需要執行一次就夠了,沒有必要在每次執行的時候都要呼叫,若呼叫的時間間隔太近的話會造成設定的種子seed全部一樣導致產生的隨機數也都一樣。

基於以上幾個特性我們稱rand產生的隨機數為「偽隨機數」。

rand的內部實現是用線性同餘法做的,他不是真的隨機數,只不過是因為其週期特別長,所以有一定的範圍裡可看成是隨機的,rand()會返回一隨機數值,範圍在0至rand_max間。

這些是數學上的內容我們不做討論。

rand()函式產生的隨機數範圍比較小只能是0x0000~0x7fff之間的整數隨機數即2^15以內的數,我們在實際的應用中經常需要用到大範圍的隨機數例如會用到2^32 以內的隨機數。顯然rand已經無法滿足我們的要求了。

這時候就要想辦法對隨機數做擴充套件,c++標準庫提供了標準的擴充套件方法rand_max*rand() + rand();這樣就在[0, rand_max*rand_max)做到了隨機。這種方法有缺點就是容易產生數的「兩端聚集」現象。但是rand*rand和rand+rand的方法做不到隨機數的擴充套件只會使得出的隨機數產生「二次聚集」現象。

有沒有一種更好的擴充套件方法呢?

有利用計算機的位偏移和位運算可以實現隨機數的更好擴充套件。

unsigned long ulrand(void)

return (

(((unsignedlong)rand()<<24)&0xff000000ul)

|(((unsignedlong)rand()<<12)&0x00fff000ul)

|(((unsigned long)rand()    )&0x00000ffful));

關於位運算我就不做過多的解釋。需要注意的一點是rand返回的隨機數最高位始終為0,並不隨機,因此不能參與隨機數擴充套件的二進位制運算。

rand()-rand_max/2這樣就產生了[-rand_max,rand_max]之間的隨機數。負隨機數的擴充套件同上。

rand()/rand_max 產生[0,1)之間的小數。

rand()/(rand_max-1) 產生[0,1]之間的小數。

倍率* 和 +起始值,可以合成我們想要的隨機數。

rand函式產生的隨機數隨機性並不夠強,範圍不夠大。我們要找另外一種更加強大的隨機數數生成函式。

boost隨機庫中利用了mersennetwister演算法,可以快速產生高質量的偽隨機數mersenne twister有以下優點:隨機性好,在計算機上容易實現,占用記憶體較少(mt19937的c程式碼執行僅需624個字的工作區域),與其它已使用的偽隨機數發生器相比,產生隨機數的速度快、周期長,可達到2^19937-1,且具有623維均勻分布的性質,對於一般的應用來說,足夠大了,序列關聯比較小,能通過很多隨機性測試。

voidtest_mt19937()

// 以時間為種子建立乙個隨機數發生器

boost::mt19937 rng(time(0));

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

std::cout << rng() 《不做過多解釋,boost的強大有點***了!

生成隨機數函式解析

c 隨機函式生成。有時候,我們需要隨機產生乙個在某範圍的隨機數,c 中rand 函式可以用來產生隨機數,但是是屬於偽隨機數。函式原型 int rand void 標頭檔案 include 返回值 返回乙個 0,rand max 間的隨機整數。其中rand max是定義在stdlib.h標頭檔案中的乙...

隨機數 偽隨機數

隨機數 偽隨機數 rand函式在產生隨機數前,需要系統提供的生成偽隨機數序列的種子,rand根據這個種子的值產生一系列隨機數。如果系統提供的種子沒有變化,每次呼叫rand函式生成的偽隨機數序列都是一樣的。srand unsigned seed 通過引數seed改變系統提供的種子值,從而可以使得每次呼...

隨機數生成 偽隨機數和真隨機數

c語言隨機數的生成,很隨機,又不隨機,比如像下面的程式 c語言生成隨機數的函式在stdlib.h庫中 include includeint main return 0 上面的 經過執行生成了 41 18467 6334 26500但是無論執行多好遍結果都是一樣的,隨機數並不隨機。這是因為rand 函...