代码改变世界

Random 学习笔记

2010-10-20 20:44  MichaelYin  阅读(409)  评论(0编辑  收藏  举报

这几天在学习算法,所以生成随机数组就不可避免了,以前只是知道Random 这个类是用来生成随机数的但是没怎么用过,这次正好趁这个机会好好了解一下,在园子里面看了下别人写的文章和代码,自己又在VS里面跑了几次,这里就把一些觉得useful的东东记下来。

Random是用来生成伪随机数的类,它根据生成对象时候的随机种子进行复杂的计算,然后生成伪随机数。如果我们在调用构造函数的时候没有指定随机种子,那么默认情况下它会采用系统的时间产生的值来做随机种子,这样的话那么我们在一次函数调用里面不同的Random对象有可能是采用相同的随机种子,那么有可能造成生成重复的随机数。关于随机种子的选取问题,等下会专门讲解。Random里面要用到比较多的方法就是obj.Next()这个方法,用于根据随机种子按照复杂的算法生成伪随机数,这个方法有多个重载的方法,可以限定需要生成的数字的最大值和最小值,基本上Random经常使用的就是这么几个东西。

下面来讲一下如何避免生成重复的随机种子,以此来避免产生一连串重复的随机数。其实关键点就在于生成随机数的随机种子必须不一样,一种方法就是采用Guid.NewGuid().GetHashCode()来当做随机种子,由于Guid重复的可能性非常小,而且Hash算法不同的输入产生的结果也是不同的,所以可以很好的解决随机种子相同的问题。还有一种方法就是采用

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

这个方法来达到效果

园子里面有的朋友是用算法来完成生成不重复随机数的,这样可以完全避免重复数据的发生。

        public static int[] CreateInstanceType2()
        {
            int[] result = new int[10];
            int tmp = -1;
            Random random = new Random();
            bool repeat = false;
            for (int i = 0; i < 10; i++)
            {
                repeat = false;
                tmp = random.Next(1, 11);
                for (int j = 0; j < i; j++)
                {
                    if (tmp == result[j])
                    {
                        repeat = true;
                        break;
                    }
                }
                if (!repeat)
                {
                    result[i] = tmp;
                }
                else
                {
                    //循环变量-1,下一次for循环继续针对这个变量值进行
                    i = i - 1;
                }
            }
            return result;
        }

这个算法执行的思想就是每次生成后面的结果的时候都和前面所生成的结果进行比较,如果有比较的则把for循环中的i减小一次,下一次循环的时候重新生成,这是一种思路

   
int[] index = new int[15];
        for (int i = 0; i < 15; i++)
        {
            index[i] = 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--;
        }

另外一种思想是首先在另外一个数组中把需要生成的结果生成,然后通过生成随机位置来确保唯一不重复随机数组。

上面提到的几种方式应该根据实际情况具体确定使用方法,一般情况下在项目中如果需要用到Random的话把它设为全局的然后直接拿来调用是种不错的使用方式。