隨機數的使用很普遍,可用它隨機顯示圖片,用它防止無聊的人在論壇灌水還可以用來加密資訊等等。本文討論如何在一段數字區間內隨機產生若干個互不相同的隨機數,比如在從1到20間隨機產生6個互不相同的整數,並通過此文介紹Visual c#中隨機數的用法。
.net.Frameword中提供了一個專門產生隨機數的類System.Random,此類預設情況下已被匯入,編程過程中可以直接使用。我們知道,電腦並不能產生完全隨機的數字,它產生的數字被稱為偽隨機數,它是以相同的機率從一組有限的數字中選取的,所選的數字並不具有完全的隨機性,但就實用而言,其隨機程度已經足夠了。
我們可以用以下兩種方法初始化一個隨機數發生器;
第一種方法不指定隨機種子,系統自動選取當前時前作隨機種子:
Random ra=new Random();
第二種方法是指定一個int型的參數作為隨機種子:
int iSeed=6;
Random ra=new Random(iSeed);
下面我們要用到Random.Next()方法產生隨機數。
ra.Next();
它返回一個大於或等於零而小於2,147,483,647的數,這並不滿足我們的需要,下面我們介紹它的重載函數和其它一些方法。
public virtual int Next(int);
用法:ra.next(20)
返回一個小於所指定最大值(此處為20)的正隨機數。
public virtual int Next(int minValue, int maxValue);
用法:ra.next(1,20)
返回一個指定範圍內(此處為1-20之間)的隨機數,我們在下面的執行個體中會用到此函數。
類System.Random還有幾個方法分別是:
公用方法:
NextBytes用隨機數填充指定位元組數組的元素。
NextDouble返回一個介於 0.0 和 1.0 之間的隨機數。
受保護的方法:
Sample返回一個介於 0.0 和 1.0 之間的隨機數,只允許子類對象訪問。
以上介紹了隨機數的基本用法,下面我們用一個執行個體來做更進一步的介紹。要在一段數字區間內隨機產生若干個互不相同的隨機數,比如在從1到20間隨機產生6個互不相同的整數。
主要是下面兩個函數getRandomNum與getNum:
public int[] getRandomNum(int num,int minValue,int maxValue){
Random ra=new Random(unchecked((int)DateTime.Now.Ticks));
int[] arrNum=new int[num];
int tmp=0;
for (int i=0;i<=num-1;i++){
tmp=ra.Next(minValue,maxValue); //隨機取數
arrNum[i]=getNum(arrNum,tmp,minValue,maxValue,ra); //取出值賦到數組中
}
return arrNum;
}
getRandomNum即是在區間[minValue,maxValue]取出num個互不相同的隨機數,返回的數組包含著結果。
其中隨機數是這樣建立的 Random ra=new Random(unchecked((int)DateTime.Now.Ticks));為什麼不用Random ra=new Random();(系統自動選取當前時前作隨機種子)呢?
用系統時間做隨機種子並不保險,如果應用程式在一個較快的電腦上運行,則該電腦的系統時鐘可能沒有時間在此建構函式的調用之間變更,Random 的不同執行個體的種子值可能相同。這種情況下,我們就需要另外的演算法來保證產生的數位隨機性。所以為了保證產生的隨機數足夠“隨機”,我們不得不使用複雜一點的方法來獲得隨機種子。 在上面的這段程式中,我們首先使用系統時間作為隨機種子,然後將上一次產生的隨機數跟迴圈變數和一個與系統時間有關的整型參數相乘,以之作為隨機種子,從而得到了每次都不同的隨機種子,保證了產生足夠“隨機”的隨機數。
函數getNum是一遞迴,用它來檢測產生的隨機數是否有重複,如果取出來的數字和已取得的數字有重複就重新隨機擷取。值得注意的是要用一同一個隨機數執行個體產生,所以ra要作為參數傳入getNum中,否則產生的數字會有重複。
public int getNum(int[] arrNum,int tmp,int minValue,int maxValue,Random ra){
int n=0;
while (n<=arrNum.Length-1)
{
if (arrNum[n]==tmp) //利用迴圈判斷是否有重複
{
tmp=ra.Next(minValue,maxValue); //重新隨機擷取。
getNum(arrNum,tmp,minValue,maxValue,ra);//遞迴:如果取出來的數字和已取得的數字有重複就重新隨機擷取。
}
n++;
}
return tmp;
}