閱讀760 返回首頁    go 阿裏雲 go 技術社區[雲棲]


用C#生成不重複的隨機數

對於隨機數,大家都知道,計算機不可能產生完全隨機的數字,所謂的隨機數發生器都是通過一定的算法對事先選定的隨機種子做複雜的運算,用產生的結果來近似的模擬完全隨機數,這種隨機數被稱 作偽隨機數。偽隨機數是以相同的概率從一組有限的數字中選取的。所選數字並不具有完全的隨機性,但是從實用的角度而言,其隨機程度已足夠了。偽隨機數的選 擇是從隨機種子開始的,所以為了保證每次得到的偽隨機數都足夠地“隨機”,隨機種子的選擇就顯得非常重要。如果隨機種子一樣,那麼同一個隨機數發生器產生 的隨機數也會一樣。一般地,我們使用同係統時間有關的參數作為隨機種子,這也是.net Framework中的隨機數發生器默認采用的方法。   我們可以使用兩種方式初始化一個隨機數發生器:

  第一種方法不指定隨機種子,係統自動選取當前時間作為隨機種子:

  Random ro = new Random();

  第二種方法可以指定一個int型參數作為隨機種子:

  int iSeed=10;
  Random ro = new Random(10);
  long tick = DateTime.Now.Ticks;
  Random ran = new Random((int)(tick & 0xffffffffL) | (int) (tick >> 32));

  這樣可以保證99%不是一樣。   之後,我們就可以使用這個Random類的對象來產生隨機數,這時候要用到Random.Next()方法。這個方法使用相當靈活,你甚至可以指定產生的隨機數的上下限。   不指定上下限的使用如下:

  int iResult;
  iResult=ro.Next();

  下麵的代碼指定返回小於100的隨機數:

  int iResult;
  int iUp=100;
  iResult=ro.Next(iUp);

  而下麵這段代碼則指定返回值必須在50-100的範圍之內:

  int iResult;
  int iUp=100;
  int iDown=50;
  iResult=ro.Next(iDown,iUp);

  除了Random.Next()方法之外,Random類還提供了Random.NextDouble()方法產生一個範圍在0.0-1.0之間的隨機的雙精度浮點數:

  double dResult;
  dResult=ro.NextDouble();

  但是用Random類生成題號,會出現重複,特別是在數量較小的題目中要生成不重複的的題目是很難的,參考了網上的一些方法,包括兩類,一類是通過隨機種子入手,使每一次的隨機種子不同,來保證不重複;第二類是使用一些數據結構和算法。下麵主要就第二類介紹幾個方法。     方法1:思想是用一個數組來保存索引號,先隨機生成一個數組位置,然後把這個位置的索引號取出來,並把最後一個索引號複製到當前的數組位置,然後使隨機 數的上限減一,具體如:先把這100個數放在一個數組內,每次隨機取一個位置(第一次是1-100,第二次是1-99,…),將該位置的數用最後的數 代替。

   int[] index = new int[15];
  for (int i = 0; i < 15; i++)
    index = i;
  Random r = new Random();
  //用來保存隨機生成的不重複的10個數
  int[] result = new int[10];
  int site = 15;//設置下限
  int id;
  for (int j = 0; j < 10; j++)
  {
    id = r.Next(1, site - 1);
       //在隨機位置取出一個數,保存到結果數組`
    result[j] = index[id];
    //最後一個數複製到當前位置
    index[id] = index[site - 1];
    //位置的下限減少一
    site--;
  }

 方法2:利用Hashtable。[NextPage]

   Hashtable hashtable = new Hashtable();
   Random rm = new Random();
  int RmNum = 10;
  for (int i = 0; hashtable.Count < RmNum; i++)
  {
      int nValue = rm.Next(100);
      if (!hashtable.ContainsValue(nValue) && nValue != 0)
      {
       hashtable.Add(nValue, nValue);
       Console.WriteLine(nValue.ToString());
      }
  }

  方法3:遞歸,用它來檢測生成的隨機數是否有重複,如果取出來的數字和已取得的數字有重複就重新隨機獲取。

  Random ra=new Random(unchecked((int)DateTime.Now.Ticks));
  int[] arrNum=new int[10];
  int tmp=0;
  int minValue=1;
  int maxValue=10;
  for (int i=0;i<10;i++)
  {
    tmp=ra.Next(minValue,maxValue); //隨機取數
    arrNum=getNum(arrNum,tmp,minValue,maxValue,ra); //取出值賦到數組中
  }
  .........
  .........
  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;
  }

最後更新:2017-04-03 08:26:26

  上一篇:go linux/Aix啟動、關閉Oracle及監聽
  下一篇:go linux/Aix啟動、關閉Oracle及監聽