c++中產生隨機數
最近在寫一個產生隨機數的程式時遇到了一個比較尷尬的事情:感覺C++中好像沒有產生隨機數的類。在網上百度之,才發現跟著自己想的一樣。大多數都是使用srand()函式與rand()函式。但是這兩個函式令人不是很放心:1、rand()函式產的資料是偽隨機的(當然計算機上產生的隨機數都是偽隨機的,但是這個比較明顯,如果srand()函式的種子相同的話,結果就相同。如果要連續產生比較好的隨機,那麼種子的選擇就非常關鍵了)。1、rand()函式產生的偽隨機數的範圍是有限的0~0x7fff。如果需要的範圍比這個小倒是好辦,求餘即可。如果比這個範圍大的話。那麼又要費神想這個擴大這個隨機數的範圍了。附上一篇講隨機數函式使用的文章(轉載):
C++中產生隨機數種子對於初學者一直都很困惑.大家知道,在C中有專門的srand(N)函式可以輕鬆實現這一功能,然而在C++中則要複雜一些.下面是筆者學習的一點心得,希望對大家能有所幫助.(這裡我們依然要藉助C標準庫中的rand()函式)
函式說明:
- int rand(); :返回從[0,MAX)之間的隨機整數,這裡的MAX與你所定義的資料型別而定;需#include <cstdlib>
-
void srand( unsigned seed ); :設定隨機數種子,#include <cstdlib>
- time_t time( time_t *time ); :返回當前時間,#include <ctime>
應用舉例:
1):
- srand(time(0)); //根據系統時間設定隨機數種子
- int i = rand() % N; //取得區間[0,N)的整數
- 如要產生1~10之間隨機數,則程式碼如下:
- #include <iostream>
-
using
- #include <ctime>
- #include <cstdlib>
- int main()
- {
- int t;
- srand(time(0)); //seed
- t = rand() % 10+ 1; // random number 1-10
- cout << t << endl;
- return 0;
- }
2):
- srand(time(0)); //根據系統時間設定隨機數種子
- float x = rand() * x / RAND_MAX; //返回1/x的概率
- 3):
- srand(time(0)); //根據系統時間設定隨機數種子
- vector<int> v; ////隨機訪問陣列型別,#include <vector>
- random_shuffle(v.begin(), v.end()); //STL演算法random_shuffle把容器類的元素順序搗亂
以下原始碼來自crafty19.3,最強的原始碼開放的chess程式。註釋很清楚,無需多言。
問:
1.Knuth的書中是怎麼講的?該書我無緣拜讀。
2.static const unsigned long x[55],這裡取55個隨機數的理由是什麼?
3.能否比較全面地講講隨機數產生的一些演算法或理論,或推薦一些參考資料?
- unsigned int Random32(void) {
- staticconst unsigned long x[55] = {
- 1410651636UL, 3012776752UL, 3497475623UL, 2892145026UL, 1571949714UL,
- 3253082284UL, 3489895018UL, 387949491UL, 2597396737UL, 1981903553UL,
- 3160251843UL, 129444464UL, 1851443344UL, 4156445905UL, 224604922UL,
- 1455067070UL, 3953493484UL, 1460937157UL, 2528362617UL, 317430674UL,
- 3229354360UL, 117491133UL, 832845075UL, 1961600170UL, 1321557429UL,
- 747750121UL, 545747446UL, 810476036UL, 503334515UL, 4088144633UL,
- 2824216555UL, 3738252341UL, 3493754131UL, 3672533954UL, 29494241UL,
- 1180928407UL, 4213624418UL, 33062851UL, 3221315737UL, 1145213552UL,
- 2957984897UL, 4078668503UL, 2262661702UL, 65478801UL, 2527208841UL,
- 1960622036UL, 315685891UL, 1196037864UL, 804614524UL, 1421733266UL,
- 2017105031UL, 3882325900UL, 810735053UL, 384606609UL, 2393861397UL };
- staticint init = 1;
- static unsigned long y[55];
- staticint j, k;
- unsigned long ul;
- if (init)
- {
- int i;
- init = 0;
- for (i = 0; i < 55; i++) y[i] = x[i];
- j = 24 - 1;
- k = 55 - 1;
- }
- ul = (y[k] += y[j]);
- if (--j < 0) j = 55 - 1;
- if (--k < 0) k = 55 - 1;
- return((unsigned int)ul);
- }
對於初學者來說,只需熟練掌握1)種用法,更深層次的隨著水平的提升自然會有所領悟.
另:
一、C++中不能使用random()函式 random函式不是ANSI C標準,不能在gcc,vc等編譯器下編譯通過。可改用C++下的rand函式來實現。 1、C++標準函式庫提供一隨機數生成器rand,返回0-RAND_MAX之間均勻分佈的偽隨機整數。 RAND_MAX必須至少為32767。rand()函式不接受引數,預設以1為種子(即起始值)。隨機數生成器總是以相同的種子開始,所以形成的偽隨機數列也相同,失去了隨機意義。(但這樣便於程式除錯)
2、C++中另一函式srand(),可以指定不同的數(無符號整數變元)為種子。但是如果種子相同,偽隨機數列也相同。一個辦法是讓使用者輸入種子,但是仍然不理想。
3、比較理想的是用變化的數,比如時間來作為隨機數生成器的種子。 time的值每時每刻都不同。所以種子不同,所以,產生的隨機數也不同。
// C++隨機函式(VC program)
- #include <stdio.h>
- #include <iostream>
- #include <time.h>
- usingnamespace std;
- #define MAX 100
- int main(int argc, char* argv[])
- {
- //srand()函式產生一個以當前時間開始的隨機種子.
- //應該放在for等迴圈語句前面不然要很長時間等待
- srand( (unsigned)time( NULL ) );
- for (int i=0;i<10;i++)
- cout<<rand()%MAX<<endl;//MAX為最大值,其隨機域為0~MAX-1
- return 0;
- }
二、rand()的用法
rand()不需要引數,它會返回一個從0到最大隨機數的任意整數,最大隨機數的大小通常是固定的一個大整數。這樣,如果你要產生0~10的10個整數,可以表達為:
int N = rand() % 11;
這樣,N的值就是一個0~10的隨機數,如果要產生1~10,則是這樣:
int N = 1 + rand() % 11;
總結來說,可以表示為:
a + rand() % n
其中的a是起始值,n是整數的範圍。 a + rand() % (b-a+1) 就表示 a~b之間的一個隨機數若要0~1的小數,則可以先取得0~10的整數,然後均除以10即可得到隨機到十分位的10個隨機小數,若要得到隨機到百分位的隨機小數,則需要先得到0~100的10個整數,然後均除以100,其它情況依
此類推。
通常rand()產生的隨機數在每次執行的時候都是與上一次相同的,這是有意這樣設計的,是為了便於程式的除錯。若要產生每次不同的隨機數,可以使用srand( seed )函式進行隨機化,隨著seed的不同,就能夠產生不同的隨機數。
如大家所說,還可以包含time.h標頭檔案,然後使用srand(time(0))來使用當前時間使隨機數發生器隨機化,這樣就可以保證每兩次執行時可以得到不同的隨機數序列(只要兩次執行的間隔超過1秒)。