如何生成不重复的随即数-急

blueyexin 2006-07-13 11:32:17
代码如下:

public class RandomNumber
{
public RandomNumber()
{
//
// TODO: Add constructor logic here
//
}
/// <summary>
/// 产生随机数
/// </summary>
/// <param name="n">位数</param>
/// <returns></returns>
public static ulong CreateRandomNumber(int n)
{
Random Ram=new Random(unchecked((int)DateTime.Now.Ticks));
ulong RamInt=Convert.ToUInt64(Ram.NextDouble()*Convert.ToUInt64(unchecked(Math.Pow(Convert.ToDouble(10),Convert.ToDouble(n)))));
return RamInt;
}

}
但是当循环调用的时候就会出现很多重复
for(int i=0;i<10000;i++)
{
Console.WriteLine(RandomNumber.CreateRandomNumber(18).ToString());
}


...全文
258 13 打赏 收藏 转发到动态 举报
写回复
用AI写文章
13 条回复
切换为时间正序
请发表友善的回复…
发表回复
www_123du_com 2006-07-13
  • 打赏
  • 举报
回复
嗯,一定会重复,理论上讲,总有用完的时候。

只是我不赞成重复了再继续生成,那么取到最后将速度超低甚至死锁。

我建议重复之后将取到的值++,再判断是否重复,如果还重复继续++,如果到达最大值时将其变成最小值,当一直轮循到最开始取的值时,说明循环了一圈,数字已经用尽,那么抛出异常,获取失败。
江城007 2006-07-13
  • 打赏
  • 举报
回复
赞同 kssys() 的说法,我也是这样做的
eliphe 2006-07-13
  • 打赏
  • 举报
回复
Random Ram=new Random(unchecked((int)DateTime.Now.Ticks));
最好是单一实体。
liaodanz 2006-07-13
  • 打赏
  • 举报
回复

我们可以用以下两种方法初始化一个随机数发生器;

第一种方法不指定随机种子,系统自动选取当前时前作随机种子:

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;
}
最后就是要显示出来,当点击一个button时取出的数字显示在一个label中。
private void button1_Click(object sender, System.EventArgs e)
{
int[] arr=getRandomNum(6,1,20); //从1至20中取出6个互不相同的随机数
int i=0;
string temp="";
while (i<=arr.Length-1){
temp+=arr[i].ToString()+"\n";
i++;
}
label1.Text=temp; //显示在label1中
}
kssys 2006-07-13
  • 打赏
  • 举报
回复
一定会重复的,生成随机后再判断是否重复,如果重复,继续获取。
cancerser 2006-07-13
  • 打赏
  • 举报
回复
为什么要生成不相同的随机数啊? 当唯一标识? i++ 不是更好
Knight94 2006-07-13
  • 打赏
  • 举报
回复
把Random Ram=new Random(unchecked((int)DateTime.Now.Ticks));
改为static成员试试
diandian82 2006-07-13
  • 打赏
  • 举报
回复
Random Ram=new Random(unchecked((int)DateTime.Now.Ticks));
写到类中试试,让Ram变成类成员。
yang20052008 2006-07-13
  • 打赏
  • 举报
回复
赞同 kssys() 的说法,就应该那样做
whmjw 2006-07-13
  • 打赏
  • 举报
回复
主要是种子不能重复,
skywolfma 2006-07-13
  • 打赏
  • 举报
回复
private void randomNumbers()
{
int[] flgBoxCardNumber = new int[52];

Random objRandom = new Random();

for(int i = 0; i < picBoxCardNumber.Length; i ++)
{
picBoxCardNumber[i] = objRandom.Next(1, 53);

while(flgBoxCardNumber[picBoxCardNumber[i] - 1] == 1)
{
picBoxCardNumber[i] = objRandom.Next(1, 53);
if(flgBoxCardNumber[picBoxCardNumber[i] - 1] == 0)
{
flgBoxCardNumber[picBoxCardNumber[i] - 1] = 1;
break;
}
}
if(flgBoxCardNumber[picBoxCardNumber[i] - 1] == 0)
{
flgBoxCardNumber[picBoxCardNumber[i] - 1] = 1;
}
}

for(int i = 0; i < 52; i ++)
{
Cards[i] = new CCards(picBoxCardNumber[i], i);
}
}

给你个例子,想要简单的自己改吧,不能老用现成的-:)
blueyexin 2006-07-13
  • 打赏
  • 举报
回复
我现在在程序的好多地方都调用了RandomNumber.CreateRandomNumber()这个方法,如果是重复判断的话势必要修改好多地方,有没有其他的办法修改生成种子的方法,这样就不用全部修改代码了
skywolfma 2006-07-13
  • 打赏
  • 举报
回复
我的都是自己写的,就是每生成一个然后就跟以前的比较,如果重复就继续生成
或者你也可以先放好一个数组从里面取,取走的以后就再也取不到了

110,537

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Web++
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧