c++簡單隨機數的獲得

隨機數、隨機數種子
在計算機中並沒有一個真正的隨機數發生器,但是可以做到使產生的數字重複率很低,這樣看起來好象是真正的隨機數,實現這一功能的程序叫偽隨機數發生器。


有關如何產生隨機數的理論有許多,如果要詳細地討論,需要厚厚的一本書的篇幅。不管用什麼方法實現隨機數發生器,都必須給它提供一個名為“種子”的初始值。而且這個值最好是隨機的,或者至少這個值是偽隨機的。“種子”的值通常是用快速計數寄存器移位寄存器來生成的。
下面講一講在C語言裡所提供的隨機數發生器的用法。現在的C編譯器都提供了一個基於ANSI標準的偽隨機數發生器函數,用來生成隨機數。它們就是rand()和srand()函數。這二個函數的工作過程如下:

  1. 首先給srand()提供一個種子,它是一個unsigned int類型,其取值範圍從0~65535;
  2. 然後調用rand(),它會根據提供給srand()的種子值返回一個隨機數(在0到32767之間)
  3. 根據需要多次調用rand(),從而不間斷地得到新的隨機數;
  4. 無論什麼時候,都可以給srand()提供一個新的種子,從而進一步“隨機化”rand()的輸出結果。

這個過程看起來很簡單,問題是如果你每次調用srand()時都提供相同的種子值,那麼,你將會得到相同的隨機數序列這時看到的現象是沒有隨機數,而每一次的數都是一樣的了
例如,在以17為種子值調用srand()之後,在首次調用rand()時,得到隨機數94。在第二次和第三次調用rand()時將分別得到26602和30017,這些數看上去是很隨機的(儘管這只是一個很小的數據點集合),但是,在你再次以17為種子值調用srand()後,在對於rand()的前三次調用中,所得的返回值仍然是在對94,26602,30017,並且此後得到的返回值仍然是在對rand()的第一批調用中所得到的其餘的返回值。因此只有再次給srand()提供一個隨機的種子值,才能再次得到一個隨機數。

要想使用隨機函數rand(),就必須先要初始化隨機種子。具體點就是在main函數的開頭加上srand((unsigned)time(NULL))就可以了,由於需要使用time所以還必須添加上time.h頭文件。

標準庫(被包含於中)提供兩個幫助生成偽隨機數的函數:
函數一:int rand(void);
從srand (seed)中指定的seed開始,返回一個[seed, RAND_MAX(0x7fff)]間的隨機整數。


函數二:void srand(unsigned seed);
參數seed是rand()的種子,用來初始化rand()的起始值。
可以認為rand()在每次被調用的時候,它會查看:
1) 如果用戶在此之前調用過srand(seed),給seed指定了一個值,那麼它會自動調用
srand(seed)一次來初始化它的起始值。
2) 如果用戶在此之前沒有調用過srand(seed),它會自動調用srand(1)一次。
根據上面的第一點我們可以得出:
1)如果希望rand()在每次程序運行時產生的值都不一樣,必須給srand(seed)中的seed一個變值,這個變值必須在每次程序運行時都不一樣(比如到目前為止流逝的時間)。
2) 否則,如果給seed指定的是一個定值,那麼每次程序運行時rand()產生的值都會一樣,雖然這個值會是[seed, RAND_MAX(0x7fff))之間的一個隨機取得的值。
3)如果在調用rand()之前沒有調用過srand(seed),效果將和調用了srand(1)再調用rand()一樣(1也是一個定值)。
舉幾個例子,假設我們要取得0~6之間的隨機整數(不含6本身):
例一,不指定seed:
for(int i=0;i<10;i++){
ran_num=rand() % 6;
cout<}
每次運行都將輸出:5 5 4 4 5 4 0 0 4 2

例二,指定seed為定值1:
srand(1);
for(int i=0;i<10;i++){
ran_num=rand() % 6;
cout<}
每次運行都將輸出:5 5 4 4 5 4 0 0 4 2
跟例子一的結果完全一樣。
例三,指定seed為定值6:
srand(6);
for(int i=0;i<10;i++){
ran_num=rand() % 6;
cout<}
每次運行都將輸出:4 1 5 1 4 3 4 4 2 2
隨機值也是在[0,6)之間,隨得的值跟srand(1)不同,但是每次運行的結果都相同。
例四,指定seed為當前系統流逝了的時間(單位為秒):time_t time(0):
#include
//…
srand((unsigned)time(0));
for(int i=0;i<10;i++){
ran_num=rand() % 6;
cout<}
第一次運行時輸出:0 1 5 4 5 0 2 3 4 2
第二次:3 2 3 0 3 5 5 2 2 3
總之,每次運行結果將不一樣,因為每次啟動程序的時刻都不同(間隔須大於1秒?見下)。
關於time_t time(0):
time_t被定義為長整型,它返回從1970年1月1日零時零分零秒到目前為止所經過的時間,單位為秒。比如假設輸出:
cout<<time>值約為1169174701,約等於37(年)乘365(天)乘24(小時)乘3600(秒)(月日沒算)。

另外,關於ran_num = rand() % 6,
將rand()的返回值與6求模是必須的,這樣才能確保目的隨機數落在[0,6)之間,否則rand()的返回值本身可能是很巨大的。
一個通用的公式是:
要取得[a,b)之間的隨機整數,使用(rand() % (b-a))+ a (結果值將含a不含b)。
在a為0的情況下,簡寫為rand() % b。
最後,關於偽隨機浮點數:
用rand() / double(RAND_MAX)可以取得0~1之間的浮點數(注意,不同於整型時候的公式,是除以,不是求模),舉例:
double ran_numf=0.0;
srand((unsigned)time(0));
for(int i=0;i<10;i++){
ran_numf = rand() / (double)(RAND_MAX);
cout<}
運行結果為:0.716636,0.457725,…等10個0~1之間的浮點數,每次結果都不同。
如果想取更大範圍的隨機浮點數,比如1~10,可以將
rand() /(double)(RAND_MAX) 改為 rand() /(double)(RAND_MAX/10)
運行結果為:7.19362,6.45775,…等10個1~10之間的浮點數,每次結果都不同。
至於100,1000的情況,如此類推。
以上不是偽隨機浮點數最好的實現方法,不過可以將就著用用…

C++中

一、C++中不能使用random()函數
C++ 中常用rand()函數生成隨機數,但嚴格意義上來講生成的只是偽隨機數(pseudo-random integral number)。生成隨機數時需要我們指定一個種子,如果在程序內循環,那麼下一次生成隨機數時調用上一次的結果作為種子。但如果分兩次執行程序,那麼由於種子相同,生成的“隨機數”也是相同的。


在工程應用時,我們一般將系統當前時間(Unix時間)作為種子,這樣生成的隨機數更接近於實際意義上的隨機數。給一下例程如下:

#include <iostream>
#include <ctime>
#include <cstdlib>
using namespace std;

int main()
{
double random(double,double);
srand(unsigned(time(0)));
for(int icnt = 0; icnt != 10; ++icnt)
cout << "No." << icnt+1 << ": " << int(random(0,10))<< endl;
return 0;
}

double random(double start, double end)
{
return start+(end-start)*rand()/(RAND_MAX + 1.0);
}
二、rand()的用法
12345678910111213141516171819/<cstdlib>/<ctime>/<iostream>

rand()不需要參數,它會返回一個從0到最大隨機數的任意整數,最大隨機數的大小通常是固定的一個大整數。這樣,如果你要產生0~10的10個整數,可以表達為:
  int N = rand() % 11;
這樣,N的值就是一個010的隨機數,如果要產生110,則是這樣:
  int N = 1 + rand() % 10;
  總結來說,可以表示為:
  a + rand() % n
其中的a是起始值,n是整數的範圍。
  a + rand() % (b-a+1) 就表示 a~b之間的一個隨機數
若要0-1的小數,可以先取得1-10的整數,然後均除以10即可得到隨機到十分位的10個隨機小數,若要得到隨機到百分位的隨機小數,則需要先得到0-100的10個整數,然後均除以100,其它情況依此類推。


通常rand()產生的隨機數在每次運行的時候都是與上一次相同的,這是有意這樣設計的,是為了便於程序的調試。若要產生每次不同的隨機數,可以使用srand( seed )函數進行隨機化,隨著seed的不同,就能夠產生不同的隨機數。
如大家所說,還可以包含time.h頭文件,然後使用srand(time(0))來使用當前時間使隨機數發生器隨機化,這樣就可以保證每兩次運行時可以得到不同的隨機數序列(只要兩次運行的間隔超過1秒)。

最後,如果你想學C/C++可以私信小編“01”獲取素材資料以及開發工具和聽課權限哦!


分享到:


相關文章: