Random快速连续产生不相同随机数
c# Random快速連續(xù)產(chǎn)生不相同隨機(jī)數(shù)的解決方案
?????? Random類是一個(gè)產(chǎn)生偽隨機(jī)數(shù)字的類,它的構(gòu)造函數(shù)有兩種,一個(gè)是直接New Random(),另外一個(gè)是New Random(Int32),前者是根據(jù)觸發(fā)那刻的系統(tǒng)時(shí)間做為種子,來(lái)產(chǎn)生一個(gè)隨機(jī)數(shù)字,后者可以自己設(shè)定觸發(fā)的種子,一般都是用UnCheck((Int)DateTime.Now.Ticks)做為參數(shù)種子,因此如果計(jì)算機(jī)運(yùn)行速度很快,如果觸發(fā)Randm函數(shù)間隔時(shí)間很短,就有可能造成產(chǎn)生一樣的隨機(jī)數(shù),因?yàn)閭坞S機(jī)的數(shù)字,在Random的內(nèi)部產(chǎn)生機(jī)制中還是有一定規(guī)律的,并非是真正意義上的完全隨機(jī)。
Random快速連續(xù)產(chǎn)生不相同隨機(jī)數(shù)的解決方案:
1、延時(shí)的辦法。
可以采用for循環(huán)的辦法,也可以采用Thread.Sleep(100);
2、提高隨機(jī)數(shù)不重復(fù)概率的種子生成方法:
static int GetRandomSeed( )
{
???????? byte[] bytes = new byte[4];
?????? System.Security.Cryptography.RNGCryptoServiceProvider rng = new?????? System.Security.Cryptography.RNGCryptoServiceProvider( );
?????? rng.GetBytes( bytes );
?????? return BitConverter.ToInt32( bytes , 0 );
}
Random random = new Random( GetRandomSeed( ) );
或者 Random sourceGen = new Random(new Guid().GetHashCode());
我們?cè)谧瞿茏詣?dòng)生成試卷的考試系統(tǒng)時(shí),常常需要隨機(jī)生成一組不重復(fù)的題目,在.net Framework中提供了一個(gè)專門用來(lái)產(chǎn)生隨機(jī)數(shù)的類System.Random。
對(duì)于隨機(jī)數(shù),大家都知道,計(jì)算機(jī)不可能產(chǎn)生完全隨機(jī)的數(shù)字,所謂的隨機(jī)數(shù)發(fā)生器都是通過(guò)一定的算法對(duì)事先選定的隨機(jī)種子做復(fù)雜的運(yùn)算,用產(chǎn)生的結(jié)果來(lái)近似的模擬完全隨機(jī)數(shù),這種隨機(jī)數(shù)被稱作偽隨機(jī)數(shù)。偽隨機(jī)數(shù)是以相同的概率從一組有限的數(shù)字中選取的。所選數(shù)字并不具有完全的隨機(jī)性,但是從實(shí)用的角度而言,其隨機(jī)程度已足夠了。偽隨機(jī)數(shù)的選擇是從隨機(jī)種子開(kāi)始的,所以為了保證每次得到的偽隨機(jī)數(shù)都足夠地“隨機(jī)”,隨機(jī)種子的選擇就顯得非常重要。如果隨機(jī)種子一樣,那么同一個(gè)隨機(jī)數(shù)發(fā)生器產(chǎn)生的隨機(jī)數(shù)也會(huì)一樣。一般地,我們使用同系統(tǒng)時(shí)間有關(guān)的參數(shù)作為隨機(jī)種子,這也是.net Framework中的隨機(jī)數(shù)發(fā)生器默認(rèn)采用的方法。
我們可以使用兩種方式初始化一個(gè)隨機(jī)數(shù)發(fā)生器:
第一種方法不指定隨機(jī)種子,系統(tǒng)自動(dòng)選取當(dāng)前時(shí)間作為隨機(jī)種子:
Random ro = new Random();
第二種方法可以指定一個(gè)int型參數(shù)作為隨機(jī)種子:
int iSeed=10;
Random ro = new Random(10);
long tick = DateTime.Now.Ticks;
Random ran = new Random((int)(tick & 0xffffffffL) | (int) (tick >> 32));
這樣可以保證99%不是一樣。
之后,我們就可以使用這個(gè)Random類的對(duì)象來(lái)產(chǎn)生隨機(jī)數(shù),這時(shí)候要用到Random.Next()方法。這個(gè)方法使用相當(dāng)靈活,你甚至可以指定產(chǎn)生的隨機(jī)數(shù)的上下限。
不指定上下限的使用如下:
int iResult;
iResult=ro.Next();
下面的代碼指定返回小于100的隨機(jī)數(shù):
int iResult;
int iUp=100;
iResult=ro.Next(iUp);
而下面這段代碼則指定返回值必須在50-100的范圍之內(nèi):
int iResult;
int iUp=100;
int iDown=50;
iResult=ro.Next(iDown,iUp);
除了Random.Next()方法之外,Random類還提供了Random.NextDouble()方法產(chǎn)生一個(gè)范圍在0.0-1.0之間的隨機(jī)的雙精度浮點(diǎn)數(shù):
double dResult;
dResult=ro.NextDouble();
但是用Random類生成題號(hào),會(huì)出現(xiàn)重復(fù),特別是在數(shù)量較小的題目中要生成不重復(fù)的的題目是很難的,參考了網(wǎng)上的一些方法,包括兩類,一類是通過(guò)隨機(jī)種子入手,使每一次的隨機(jī)種子不同,來(lái)保證不重復(fù);第二類是使用一些數(shù)據(jù)結(jié)構(gòu)和算法。下面主要就第二類介紹幾個(gè)方法。
??? 方法1:思想是用一個(gè)數(shù)組來(lái)保存索引號(hào),先隨機(jī)生成一個(gè)數(shù)組位置,然后把這個(gè)位置的索引號(hào)取出來(lái),并把最后一個(gè)索引號(hào)復(fù)制到當(dāng)前的數(shù)組位置,然后使隨機(jī)數(shù)的上限減一,具體如:先把這100個(gè)數(shù)放在一個(gè)數(shù)組內(nèi),每次隨機(jī)取一個(gè)位置(第一次是1-100,第二次是1-99,...),將該位置的數(shù)用最后的數(shù)代替。
? int[] index = new int[15];
for (int i = 0; i < 15; i++)
index = i;
Random r = new Random();
//用來(lái)保存隨機(jī)生成的不重復(fù)的10個(gè)數(shù)
int[] result = new int[10];
int site = 15;//設(shè)置下限
int id;
for (int j = 0; j < 10; j++)
{
id = r.Next(1, site - 1);
//在隨機(jī)位置取出一個(gè)數(shù),保存到結(jié)果數(shù)組
result[j] = index[id];
//最后一個(gè)數(shù)復(fù)制到當(dāng)前位置
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:遞歸,用它來(lái)檢測(cè)生成的隨機(jī)數(shù)是否有重復(fù),如果取出來(lái)的數(shù)字和已取得的數(shù)字有重復(fù)就重新隨機(jī)獲取。
? 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); //隨機(jī)取數(shù)
arrNum=getNum(arrNum,tmp,minValue,maxValue,ra); //取出值賦到數(shù)組中
}
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) //利用循環(huán)判斷是否有重復(fù)
{
tmp=ra.Next(minValue,maxValue); //重新隨機(jī)獲取。
getNum(arrNum,tmp,minValue,maxValue,ra);//遞歸:如果取出來(lái)的數(shù)字和已取得的數(shù)字有重復(fù)就重新隨機(jī)獲取。
}
n++;
}
return tmp;
}?
轉(zhuǎn)載于:https://www.cnblogs.com/flyinghigher/archive/2012/12/21/2828132.html
總結(jié)
以上是生活随笔為你收集整理的Random快速连续产生不相同随机数的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: U-Mail邮件服务器树状通讯录实现智能
- 下一篇: _CRT_SECURE_NO_WARNI