關於產生不重復隨機數的算法 C#


我們不得不承認這樣一個事實:那就是盡管在高級程序語言設計中包含了類似於Random產生隨機數之類的方法,但是它產生的隨機數並不能滿足我們日常所有需要,因為它可能重復——設想一下,電子化抽取試題的原理就是根據預定產生的題目數量產生果敢若干個對應的隨機數,然后將匹配的試題抽取、排序並打印在試卷上。但是在同一次考試時候不允許同一題目出現重復(盡管這樣的概率很低,但是我們絕對不允許這樣做!)。所以避免產生重復隨機數的方法(產生“真正的隨機數”)成了我們必須研究的話題。今天本文就討論一下。


方法1:去重法
這是最容易想到的方法,逐個產生這些隨機數,每產生一個,都跟前面的隨機數比較,如果重復,就重新產生。 這種方法效率比較低,且比較次數呈線性增長,越往后次數越多。


方法2:篩選法

所謂“篩選法”就是根據要產生隨機數指定的范圍(起始數必須小於終止數),將這些數全部裝入一個數組,然后利用系統隨機函數(比如 Random )隨機產生一個下標,將這個下標對應的數值返回並刪除對應的這個數,直到這個數組為空。 

public sealed class TureRandom  
{  
    private ArrayList nums=new ArrayList();  
  
    public TureRandom (int startnum, int endnum)  
    {  
        if (startnum >= endnum)   
            throw new Exception("對不起,起始數字必須小於結尾數字!")  
        else  
           for (int i=startnum; i<=endnum;++i)  
                nums.Add(i);  
         
    }  
  
    public int GetNum()  
    {  
        if (nums.Count <= 0) Then  
            throw new Exception("對不起,指定范圍的隨機數全部產生過了。")  
        else  
          {  
            Random r = new Random();  
            int index=(int)(r.NextDouble()*10+1);  
            int returnnum =(int)(nums[index]);  
            nums.RemoveAt(index);  
            return returnnum;  
            }  
    }  
}  

方法3:

int a[100]={0};
int i, m;
for(i=1; i<=99; ++i)
{
        while(a[m=rand()%100]);
        a[m] = i;
}

這段代碼也是隨機產生位置,但它預先把整個數組初始化為0,然后隨機產生其中一個位置,如果該元素 值為0,表示這個位置還沒有被使用過,就把i賦予它;否則,就重新隨機產生另一個位置,直到整個數組 被填滿。


方法4:

int a[100];
for(i=0; i<=99; ++i) a[i]=i;
for(i=99; i>=1; --i) swap(a[i], a[rand()%i]);

上面這段代碼只需要遍歷一次就可以產生這100個不重復的隨機數,它是如何做到的呢?首先第二行按順 序用0到99填滿整個數組;第三行,是隨機產生從0到m-2個數組下標,把這個下標的元素值跟m-1下標的元 素值交換,一直進行到下標為1的元素。因此它只需要遍歷一次就能產生全部的隨機數。


轉載出處:http://blog.chinaunix.net/uid-20384806-id-1954354.html

關於這些方法中算法的性能和效率,參閱:http://www.cnblogs.com/eaglet/archive/2011/01/17/1937083.html。

      http://www.nowamagic.net/program/program_GenerateRandomNumbers.php



免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM