<一>
C/C++怎樣產生隨機數:這裡要用到的是rand()函數, srand()函數,C語言/C++裡沒有內建的random(int number)函數。
(1) 如果你只要產生隨機數而不需要定義範圍的話,你只要用rand()就可以了:rand()會返回一隨機數值, 範圍在0至RAND_MAX 間。RAND_MAX定義在stdlib.h, 其值為2147483647。
例如:
#include
#include
void main()
{
for(int i=0;i<10;i+)
printf("%d/n",rand());
}
(2) 如果你要隨機產生一個在一定範圍的數,你可以在宏定義中定義一個random(int number)函數,然後在main()裡面直接調用random()函數:
例如:隨機產生10個0~100的數:
#include
#include
#define random(x) (rand()%x)
void main()
{
for(int x=0;x<10;x++)
printf("%d/n",random(100));
}
(3)但是上面兩個例子所產生的隨機數都只能是一次性的,如果你第二次啟動並執行時候輸出結果仍和第一次一樣。這與srand()函數有關。srand()用來設定rand()產生隨機數時的隨機數種子。在調用rand()函數產生隨機數前,必須先利用srand()設好隨機數種子(seed), 如果未設隨機數種子, rand()在調用時會自動設隨機數種子為1。上面的兩個例子就是因為沒有設定隨機數種子,每次隨機數種子都自動設成相同值1 ,進而導致rand()所產生的隨機數值都一樣。
srand()函數定義 : void srand (unsigned int seed);
通常可以利用geypid()或time(0)的傳回值來當做seed
如果你用time(0)的話,要加入標頭檔#include
例如:
#include
#include
#include
#define random(x) (rand()%x)
void main()
{
srand((int)time(0));
for(int x=0;x<10;x++)
printf("%d/n",random(100));
}
這樣兩次啟動並執行結果就會不一樣了!!
<二>
標準C庫中函數rand()可以產生0~RAND_MAX之間的一個隨機數,其中RAND_MAX 是stdlib.h 中定義的一個整數,它與系統有關。
rand()函數沒有輸入參數,直接通過運算式rand()來引用;例如可以用下面的語句來列印兩個隨機數:
printf("Random numbers are: %i %i/n",rand(),rand());
因為rand()函數是按指定的順序來產生整數,因此每次執行上面的語句都列印相同的兩個值,所以說C語言的隨即並不是正真意義上的隨機。
為了時程式在每次執行時都能產生一個新序列的隨機值,我們通常通過為隨機數產生器提供一粒新的隨機種子。函數srand()(來自stdlib.h)可以為隨機數產生器播散種子。只要種子不同rand()函數就會產生不同的隨機數序列。srand()稱為隨機數產生器的初始化器。
常式:
檔案名稱:
rand_srand.c
#include
#includ
int main()
{
usigned int seed;
int k;
pringt("Enter a positive integer seed value: /n");
scanf("%u",&seed);
srand(seed);
printf("Random Numbers are:/n");
for(k = 1; k <= 10; k++)
printf("%i",rand());
printf("/n");
return 0;
}
你會發現,當你提供的種子相同時,隨機數序列也時相同的。而且當種子為1時,與不使用srand()函數時一樣的,也就是說rand()函數預設情況下初始化種子值為1;
在stdlib.h 中這兩個函數的原型是:
int rand();
void srand (unsigned int);
擴充:
x = rand();
y = rand()Q - 25;
z = ((double)rand()/RAND_MAX)*(b-a) + a;
<三>
1-0:Microsoft VC++產生隨機數的原理:
Srand ( )和Rand( )函數。它本質上是利用線性同餘法,y=ax+b(mod m)。其中a,b,m都是常數。因此rand的產生決定於x,x被稱為Seed。Seed需要程式中設定,一般情況下取系統時間作為種子。它產生的隨機數之間的相關性很小,取值範圍是0—32767(int),即雙位元組(16位元),若用unsigned int 雙位元組是65535,四位元組是4294967295,一般可以滿足要求。
1-1: 線性同餘法:
?/P>
其中M是模數,A是乘數,C是增量,為初始值,當C=0時,稱此演算法為乘同餘法;若C≠0,則稱演算法為混合約餘法,當C取不為零的適當數值時,有一些優點,但優點並不突出,故常取C=0。模M大小是發生器周期長短的主要標誌,常見有M為素數,取A為M的原根,則周期T=M-1。例如:
a=1220703125
a=32719 (程式中用此組數)
a=16807
代碼:
void main( )
{
const int n=100;
double a=32719,m=1,f[n+1],g[n],seed;
m=pow(2,31);
cout<<"設定m值為 "<<m-1<<endl;
cout<<"輸入種子"<<endl; //輸入種子
cin>>seed;
f[0]=seed;
for(int i=1;i<=n;i++) //線性同餘法產生隨機數
{
f[i]=fmod((a*f[i-1]),(m-1));
g[i-1]=f[i]/(m-1);
cout.setf(ios::fixed);cout.precision(6); //設定輸出精度
cout<<i<<" "<<'/t'<<g[i-1]<<endl;
}
}
結果分析:統計資料的平均值為:0.485653
統計資料的方差為:0.320576
1-2:人字映射
遞推公式
?/P>
就是有名的混沌映射中的“人字映射”或稱“帳篷映射”,它的非周期軌道點的分布密度函數:人字映射與線性同餘法結合,可產生統計性質優良的均勻隨機數。
for(int i=1;i<=n;i++) //線性同餘法產生隨機數
{
f[i]=fmod((a*f[i-1]),m);
if(f[i]<=m/2) //與人字映射結合產生隨機數
{
f[i]=2*f[i];
}
else
{
f[i]=2*(m-f[i])+1;
}
1-3:平方取中法——馮·諾伊曼
1946年前後,由馮·諾伊曼提出,他的辦法是去前面的隨機數的平方,並抽取中部的數字。例如要產生10位元字,而且先前的值是5772156649,平方後得到33317792380594909201,所以下一個數是7923805949。
for(j=1;j<=n;j++)
{
i[j]=i[j-1]*i[j-1];
i[j]=i[j]/pow(10,5);
i[j]=fmod(i[j],pow(10,10));
g[j]=i[j]/pow(10,10);
cout.setf(ios::fixed);cout.precision(6); //設定輸出精度
cout<<j<<'/t'<<g[j]<<endl;
}
二:任意分布隨機數的產生
利用(0,1)均勻分布的隨機數可以產生任意分布的隨機數。主要的方法有反函數法,舍選法,離散逼近法,極限近似法和隨機變數函數法等。這裡主要討論了反函數法,當然對於具體分布函數可以採用不同的方法。
設隨機變數X具有分布函數F(X),則對一個給定的分布函數值,X的值為
其中inv表示反函數。現假設r是(0,1)均勻分布的隨機變數R的一個值,已知R的分布函數為
因此,如果r是R的一個值,則X具有機率
也就是說如果 (r1,r2,...,rn)是R的一組值,則相應可得到的一組值
具有分布。從而,如果我們已知分布函數的反函數,我們就可以從(0,1)分布的均勻分布隨機數得到所需分布的隨機數了。
1-4:指數分布:
指數分布的分布函數為:
x<0時,F(x)=0 ; ,F(x)=1-exp
利用上面所述反函數法,可以求得: x= ln(1-y),這裡不妨取常數為1.
for(int j=0;j
{
i=rand()0;//產生從0-32767的任意一個值
a[j]=double(i)/double(100);
a[j]=-log(a[j]);// 常數大於0,這裡取1
、、、、、、、
1-5:常態分佈:
常態分佈的機率密度是:
常態分佈的分布函數是:
對於常態分佈,利用反函數的方法來擷取常態分佈序列顯然是很麻煩的,牽涉到很複雜的積分微分運算,同時為了方便,我們取,即標準常態分佈。因此這裡介紹了兩種演算法:
第一種:
Box和Muller在1958年給出了由均勻分布的隨機變數產生常態分佈的隨機變數的演算法。設U1, U2是區間 (0, 1)上均勻分布的隨機變數,且相互獨立。令
X1=sqrt(-2*log(U1)) * cos(2*PI*U2);
X2=sqrt(-2*log(U1)) * sin(2*PI*U2);
那麼X1, X2服從N(0,1)分布,且相互獨立。
p=rand()0;//產生從0-32767的任意一個值
b[j]=double(p)/double(100);
a[j]=sqrt(-2*log(a[j]))*cos(2*3.1415926*b[j]);
第二種:
近似產生標準常態分佈,獨立同分布的多個隨機變數和的分布趨近於常態分佈,取k個均勻分布的(0,1)隨機變數,,…… ,則它們的和近似服從常態分佈。
實踐中,取k=12,(因為D( )=1/12),則新的隨機變數y=x1+x2+...+x12-6,可以求出數學期望E(y)=0,方差D(y)=12*1/12=1,因此可以近似描述標準常態分佈。