在現實計算機上無法產生真正的隨機數,因此在隨機化算法中使用的隨機數都是一定程度上隨機的,即僞隨機數。線性同餘法是產生僞隨機數最常用的方法(這裏不介紹)。
下面用計算機產生大的僞隨機數來模擬拋硬幣試驗。假設拋10次硬幣,每次拋硬幣得到正面和反面是隨機的。拋10次硬幣構成一個事件。調用Random(2)返回一個二值結果。返回0表示拋硬幣得到反面,返回1表示得到正面。下面的算法TossCoins模擬拋10次硬幣這一事件。在主程序中反覆用函數TossCoins模擬拋10次硬幣這一事件50000次。用head[i](0<=i<=10)記錄這50000次模擬恰好得到i次正面的次數。最終輸出模擬拋硬幣時間得到正面事件的頻率圖。
#include<iostream>
#include<time.h>
#include <iomanip>
using namespace std;
//隨機數類
const unsigned long maxshort=65536L;
const unsigned long multiplier=1194211693L;
const unsigned long adder=12345L;
class RandomNumber
{
private:
//當前種子
unsigned long randSeed;
public:
RandomNumber(unsigned long s=0); //構造函數,默認值0表示由系統自動生成種子
unsigned short Random(unsigned long n); //產生0到n-1之間的隨機數
double fRandom(void); //產生[0,1)之間的隨機數
};
RandomNumber::RandomNumber(unsigned long s) //產生種子
{
if(s==0)
randSeed=time(0); //用系統時間產生種子
else
randSeed=s; //由用戶提供種子
}
unsigned short RandomNumber::Random(unsigned long n) //產生0到n-1之間的隨機整數
{
randSeed=multiplier*randSeed+adder;
return(unsigned short)((randSeed>>16)%n);
}
double RandomNumber::fRandom(void) //產生[0,1)之間的隨機數
{
return Random(maxshort)/double(maxshort);
}
int TossCoins(int numberCoins)
{
//隨機拋硬幣
static RandomNumber coinToss;
int i,tosses=0;
for(i=0;i<numberCoins;i++)
//Random(2)=1表示正面
tosses+=coinToss.Random(2);
return tosses;
}
//測試
void main(void)
{
//模擬隨機拋硬幣
const int NCOINS=10;
const long NTOSSES=50000L;
//head[i]是得到i次正面的次數
long i,heads[NCOINS+1];
int j,position;
//初始化數組heads;
for(j=0;j<NCOINS+1;j++)
heads[j]=0;
//重複50 000次模擬實驗
for(i=0;i<NTOSSES;i++)
heads[TossCoins(NCOINS)]++;
//輸出頻率圖
for(i=0;i<=NCOINS;i++)
{
position=int(float(heads[i])/NTOSSES*72);
cout<<setw(6)<<i<<" ";
for(j=0;j<position-1;j++)
cout<<" ";
cout<<"*"<<endl;
}
}
/*
結果:
0 *
1 *
2 *
3 *
4 *
5 *
6 *
7 *
8 *
9 *
10 *
Press any key to continue
*/