黑马程序员技术交流社区

标题: 关于Random()函数详解 [打印本页]

作者: nooooy    时间: 2013-10-16 23:37
标题: 关于Random()函数详解
本帖最后由 nooooy 于 2013-10-16 23:52 编辑

  随机数的使用很普遍,可用它随机显示图片,用它防止无聊的人在论坛灌水还可以用来加密信息等等。本文讨论如何在一段数字区间内随机生成若干个互不相同的随机数,比如在从1到20间随机生成6个互不相同的整数,并通过此文介绍Visual c#中随机数的用法。.net.Frameword中提供了一个专门产生随机数的类System.Random,此类默认情况下已被导入,编程过程中可以直接使用。我们知道,计算机并不能产生完全随机的数字,它生成的数字被称为伪随机数,它是以相同的概率从一组有限的数字中选取的,所选的数字并不具有完全的随机性,但就实用而言,其随机程度已经足够了。
我们可以用以下两种方法初始化一个随机数发生器;
函数是这样用,比如100至999的随机数
Random ran=new Random();
int RandKey=ran.Next(100,999);
不过这样会有重复,可以给Random一个系统时间做为参数,以此产生随机数,就不会重复了
第一种方法不指定随机种子,系统自动选取当前时前作随机种子: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:

  1. <P>    public int[] getRandomNum(int num,int minValue,int maxValue)
  2.       {
  3.            Random ra=new Random(unchecked((int)DateTime.Now.Ticks));
  4.            int[] arrNum=new int[num];
  5.            int tmp=0;
  6.              for (int i=0;i<=num-1;i++)
  7.           {
  8.             tmp=ra.Next(minValue,maxValue); //随机取数
  9.             arrNum[i]=getNum(arrNum,tmp,minValue,maxValue,ra); //取出值赋到数组中</P>
  10. <P>        return arrNum;
  11.           }
  12.        }
  13. </P>
复制代码
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); //重新随机获取。</P>
                  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.ToString()+"\n";i++;
             }
           label1.Text=temp; //显示在label1中
           }
Random类是一个产生伪随机数字的类,它的构造函数有两种,一个是直接New Random(),另外一个是New Random(Int32),前者是根据触发那刻的系统时间做为种子,来产生一个随机数字,后者可以自己设定触发的种子,一般都是用UnCheck((Int)DateTime.Now.Ticks)做为参数种子,因此如果计算机运行速度很快,如果触发Randm函数间隔时间很短,就有可能造成产生一样的随机数,因为伪随机的数字,在Random的内部产生机制中还是有一定规律的,并非是真正意义上的完全随机。Random类产生随机数字的主要办法是Next(),Next(100)产生一个比100小的正整数,Next(1,100)在1到100中间产生一个随机数字,而利用Ticks(以100毫秒做基础单位的时间数量单位)来产生随机数,还是存在合理性的。
作者: 许庭洲    时间: 2013-10-17 22:16
值得学习ing!




欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2