1. 程式人生 > >c++中產生隨機數

c++中產生隨機數

最近在寫一個產生隨機數的程式時遇到了一個比較尷尬的事情:感覺C++中好像沒有產生隨機數的類。在網上百度之,才發現跟著自己想的一樣。大多數都是使用srand()函式與rand()函式。但是這兩個函式令人不是很放心:1、rand()函式產的資料是偽隨機的(當然計算機上產生的隨機數都是偽隨機的,但是這個比較明顯,如果srand()函式的種子相同的話,結果就相同。如果要連續產生比較好的隨機,那麼種子的選擇就非常關鍵了)。1、rand()函式產生的偽隨機數的範圍是有限的0~0x7fff。如果需要的範圍比這個小倒是好辦,求餘即可。如果比這個範圍大的話。那麼又要費神想這個擴大這個隨機數的範圍了。附上一篇講隨機數函式使用的文章(轉載):

     C++中產生隨機數種子對於初學者一直都很困惑.大家知道,在C中有專門的srand(N)函式可以輕鬆實現這一功能,然而在C++中則要複雜一些.下面是筆者學習的一點心得,希望對大家能有所幫助.(這裡我們依然要藉助C標準庫中的rand()函式)

  函式說明:

  1. int rand();                                          :返回從[0,MAX)之間的隨機整數,這裡的MAX與你所定義的資料型別而定;需#include <cstdlib>  
  2.  void srand( unsigned seed );                         :設定隨機數種子,#include <cstdlib>  
  3.  time_t time( time_t *time );                         :返回當前時間,#include <ctime>  

應用舉例:
1):

  1. srand(time(0));                                           //根據系統時間設定隨機數種子
  2. int i = rand() % N;                                       //取得區間[0,N)的整數
  3. 如要產生1~10之間隨機數,則程式碼如下:  
  4. #include <iostream>
  5. using
    namespace std;  
  6. #include <ctime>
  7. #include <cstdlib>
  8. int main()  
  9. {  
  10.          int t;  
  11.          srand(time(0));       //seed
  12.          t = rand() % 10+ 1;       // random number 1-10
  13.          cout << t << endl;  
  14.          return 0;  
  15. }  

2):

  1. srand(time(0));                                             //根據系統時間設定隨機數種子
  2. float x = rand() * x / RAND_MAX;                          //返回1/x的概率
  3. 3):  
  4. srand(time(0));                                           //根據系統時間設定隨機數種子
  5. vector<int> v;                                            ////隨機訪問陣列型別,#include <vector>
  6. random_shuffle(v.begin(), v.end());              //STL演算法random_shuffle把容器類的元素順序搗亂


以下原始碼來自crafty19.3,最強的原始碼開放的chess程式。註釋很清楚,無需多言。
問:
1.Knuth的書中是怎麼講的?該書我無緣拜讀。
2.static const unsigned long x[55],這裡取55個隨機數的理由是什麼?
3.能否比較全面地講講隨機數產生的一些演算法或理論,或推薦一些參考資料?

  1. unsigned int Random32(void) {  
  2.     staticconst unsigned long x[55] = {  
  3.       1410651636UL, 3012776752UL, 3497475623UL, 2892145026UL, 1571949714UL,  
  4.       3253082284UL, 3489895018UL, 387949491UL, 2597396737UL, 1981903553UL,  
  5.       3160251843UL, 129444464UL, 1851443344UL, 4156445905UL, 224604922UL,  
  6.       1455067070UL, 3953493484UL, 1460937157UL, 2528362617UL, 317430674UL,  
  7.       3229354360UL, 117491133UL, 832845075UL, 1961600170UL, 1321557429UL,  
  8.       747750121UL, 545747446UL, 810476036UL, 503334515UL, 4088144633UL,  
  9.       2824216555UL, 3738252341UL, 3493754131UL, 3672533954UL, 29494241UL,  
  10.       1180928407UL, 4213624418UL, 33062851UL, 3221315737UL, 1145213552UL,  
  11.       2957984897UL, 4078668503UL, 2262661702UL, 65478801UL, 2527208841UL,  
  12.       1960622036UL, 315685891UL, 1196037864UL, 804614524UL, 1421733266UL,  
  13.       2017105031UL, 3882325900UL, 810735053UL, 384606609UL, 2393861397UL };  
  14.     staticint init = 1;  
  15.     static unsigned long y[55];  
  16.     staticint j, k;  
  17.     unsigned long ul;  
  18.     if (init)  
  19.     {  
  20.       int i;  
  21.       init = 0;  
  22.       for (i = 0; i < 55; i++) y[i] = x[i];  
  23.       j = 24 - 1;  
  24.       k = 55 - 1;  
  25.     }  
  26.     ul = (y[k] += y[j]);  
  27.     if (--j < 0) j = 55 - 1;  
  28.     if (--k < 0) k = 55 - 1;  
  29.     return((unsigned int)ul);  
  30. }  

對於初學者來說,只需熟練掌握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)

  1. #include <stdio.h>
  2. #include <iostream>
  3. #include <time.h>
  4. usingnamespace std;   
  5. #define MAX 100
  6. int main(int argc, char* argv[])  
  7. {  
  8.      //srand()函式產生一個以當前時間開始的隨機種子.
  9.      //應該放在for等迴圈語句前面不然要很長時間等待
  10.      srand( (unsigned)time( NULL ) );  
  11.    for (int i=0;i<10;i++)  
  12.    cout<<rand()%MAX<<endl;//MAX為最大值,其隨機域為0~MAX-1
  13.    return 0;  
  14. }  

二、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秒)。