C# Random 生成不重複隨機數

轉載自   https://www.cnblogs.com/huangfr/archive/2012/03/27/2420464.html

Random 類

命名空間:System

表示僞隨機數生成器,一種能夠產生滿足某些隨機性統計要求的數字序列的設備。

僞隨機數是以相同的概率從一組有限的數字中選取的。所選數字並不具有完全的隨機性,因爲它們是用一種確定的數學算法選擇的,但是從實用的角度而言,其隨機程度已足夠了。

僞隨機數的生成是從種子值開始。如果反覆使用同一個種子,就會生成相同的數字系列。產生不同序列的一種方法是使種子值與時間相關,從而對於 Random 的每個新實例,都會產生不同的系列。默認情況下,Random 類的無參數構造函數使用系統時鐘生成其種子值,而參數化構造函數可根據當前時間的計時週期數採用 Int32 值。但是,因爲時鐘的分辨率有限,所以,如果使用無參數構造函數連續創建不同的 Random 對象,就會創建生成相同隨機數序列的隨機數生成器。

通過創建單個而不是多個 Random 對象可以避免此問題。

若要提高性能,請創建一個隨時間推移能生成多個隨機數的 Random 對象,而不要反覆新建會生成同一個隨機數的 Random 對象。

 

Random 成員

名稱 ● 說明

Equals ● 確定指定的 Object 是否等於當前的 Object。(繼承自 Object。)
Finalize ● 允許 Object 在“垃圾回收”回收 Object 之前嘗試釋放資源並執行其他清理操作。(繼承自 Object。)
GetHashCode ● 用作特定類型的哈希函數。(繼承自 Object。)
GetType ● 獲取當前實例的 Type。(繼承自 Object。)
MemberwiseClone ● 創建當前 Object 的淺表副本。(繼承自 Object。)
Next ● 已重載。 返回隨機數。
NextBytes ● 用隨機數填充指定字節數組的元素。
NextDouble ● 返回一個介於 0.0 和 1.0 之間的隨機數。
Sample ● 返回一個介於 0.0 和 1.0 之間的隨機數。
ToString ● 返回表示當前 Object 的 String。(繼承自 Object。)

 

 

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

 

我們可以使用兩種方式初始化一個隨機數發生器:

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

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。

 

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;
}

 

silverlight 2 Random 隨機數解決方案

來源:我和未來有約會
2008-06-17 01:21 by nasa

using System;
using System.Security.Cryptography;

    public class RNG
    {
        private static RNGCryptoServiceProvider rngp = new RNGCryptoServiceProvider();
        private static byte[] rb = new byte[4];

        /// <summary>
        /// 產生一個非負數的亂數
        /// </summary>
        public static int Next()
        {
            rngp.GetBytes(rb);
            int value = BitConverter.ToInt32(rb, 0);
            if (value < 0) value = -value;
            return value;
        }
        /// <summary>
        /// 產生一個非負數且最大值在 max 以下的亂數
        /// </summary>
        /// <param name="max">最大值</param>
        public static int Next(int max)
        {
            rngp.GetBytes(rb);
            int value = BitConverter.ToInt32(rb, 0);
            value = value % (max + 1);
            if (value < 0) value = -value;
            return value;
        }
        /// <summary>
        /// 產生一個非負數且最小值在 min 以上最大值在 max 以下的亂數
        /// </summary>
        /// <param name="min">最小值</param>
        /// <param name="max">最大值</param>
        public static int Next(int min, int max)
        {
            int value = Next(max - min) + min;
            return value;
        }
    }

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章