c# Random太快产生的随机数会重复

c# Random快速连续产生相同随机数的解决方案

Random类是一个产生伪随机数字的类,它的构造函数有两种,一个是直接New Random(),另外一个是New Random(Int32),前者是根据触发那刻的系统时间做为种子,来产生一个随机数字,后者可以自己设定触发的种子,一般都是用UnCheck((Int)DateTime.Now.Ticks)做为参数种子,因此如果计算机运行速度很快,如果触发Randm函数间隔时间很短,就有可能造成产生一样的随机数,因为伪随机的数字,在Random的内部产生机制中还是有一定规律的,并非是真正意义上的完全随机

Random快速连续产生相同随机数的解决方案:

1、延时的办法。

可以采用for循环的办法,也可以采用Thread.Sleep(100);

2、提高随机数不重复概率的种子生成方法:

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());

我们在做能自动生成试卷的考试系统时,常常需要随机生成一组不重复的题目,在.net
Framework中提供了一个专门用来产生随机数的类System.Random
  对于随机数,大家都知道,计算机不可能产生完全随机的数字,所谓的随机数发生器都是通过一定的算法对事先选定的随机种子做复杂的运算,用产生的结果来近似的模拟完全随机数,这种随机数被称作伪随机数。伪随机数是以相同的概率从一组有限的数字中选取的。所选数字并不具有完全的随机性,但是从实用的角度而言,其随机程度已足够了。伪随机数的选择是从随机种子开始的,所以为了保证每次得到的伪随机数都足够地“随机”,随机种子的选择就显得非常重要。如果随机种子一样,那么同一个随机数发生器产生的随机数也会一样。一般地,我们使用同系统时间有关的参数作为随机种子,这也是.net
Framework中的随机数发生器默认采用的方法。
  我们可以使用两种方式初始化一个随机数发生器:
  第一种方法不指定随机种子,系统自动选取当前时间作为随机种子:
  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。[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:递归,用它来检测生成的随机数是否有重复,如果取出来的数字和已取得的数字有重复就重新随机获取。

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

时间: 2024-11-05 20:39:32

c# Random太快产生的随机数会重复的相关文章

RxJava 并发之数据流发射太快如何办

Backpressure Rx 中的数据流是从一个地方发射到另外一个地方.每个地方处理数据的速度是不一样的.如果生产者发射数据的速度比消费者处理的快会出现什么情况?在同步操作中,这不是个问题,例如: // Produce Observable<Integer> producer = Observable.create(o -> { o.onNext(1); o.onNext(2); o.onCompleted(); }); // Consume producer.subscribe(i

冥想:节奏太快,给心灵一点歇息的时间

http://www.nowamagic.net/librarys/eight/posts/2461开始冥想是半年前,因为一个朋友很相信这方面东西,受他影响,后来慢慢尝试,感觉效果非常的好,喜欢上了冥想,也感受它带来的好的影响.之前到现在都没有看过任何过于冥想的书,所以只能凭自己半年来的经验小分享下... 为什么要冥想呢?首先,我觉得冥想带来的好处是,让自己的生活节奏慢下来,缓解生活的压力,多一些思考的时间.现在人的生活节奏太快,不停的往上赶,没有有效放松和释放压力的方式,累了想到的放松方式就是

在嵌入式学习过程中的困惑——有人说软件技术变化太快,现在学的东西过两年就要完全淘汰,是吗?

有人说软件技术变化太快,现在学的东西过两年就要完全淘汰,是吗? 你知道这话是什么人说的吗?必然是已经被淘汰的人说的.比如Delphi.BCB.PB这些开发工具和语言,都曾经很是风光了一阵,但现在已经完全被Java和.NET取代了.那么Java和.NET会不会被取代呢,也许在相当长的时间内还不会. 这些被淘汰的程序员有一些共同的特点:只会用鼠标拖拽控件,离开IDE就不知道如何工作,学点儿花拳绣腿的功夫就想吃一辈子,对学习新技术不感兴趣,做一天和尚撞一天钟.现在请回头看看1,在整个软件技术领域,这些

玩法变化太快?今天我来告诉你App推广怎么玩

无论你是刚刚进入移动互联网推广的小菜鸟,还是已经在这个行业摸爬滚打数年的老兵.无论哪个阶段你都会碰到各种各样的棘手的问题.从一开始的APP怎么做分发?到最后的一个月上千万的预算怎么去花.这些问题无时无刻的都困扰着移动互联网市场从业者的脑边.更重要的是App推广的玩法变得太快,从一开始的应用商店到积分墙再到现在的信息流广告,短短一两年你会发现以前的经验现在已经用不上了."不进则退"是移动互联网推广从业者必须深刻认识到的一个问题. APP推广到底是干什么的?是应用商店的渠道推广?还是媒介广

《java入门第一季》之HashSet小案例:获取10个1至20的随机数,要求随机数不能重复

这是基于HashSet集合的唯一性. /* * 编写一个程序,获取10个1至20的随机数,要求随机数不能重复. * * 分析: * A:创建随机数对象 * B:创建一个HashSet集合 * C:判断集合的长度是不是小于10 * 是:就创建一个随机数添加 * 否:不搭理它 * D:遍历HashSet集合 */ 代码写了出来: import java.util.HashSet; import java.util.Random; public class HashSetDemo { public s

c#学习之数组 36选7随机数不重复/折半取余

内容: 数组的定义是:数据类型[] 变量名=new 数据类型[n]  变量名.Length表示数组数值长度: 36选7随机数不重复static void Main(string[] args) { int[] a = new int[7];//1)先创建一维数组 Random rand = new Random();//2)定义随机电脑生成随机数: for (int i = 0; i < 7; i++)//3)进行筛分将重复的数字去掉 { int n = rand.Next(36);//随机生成

给数组添加一个根据指定下标删除元素的方法、得到0-100的随机数不重复(js)、得到外联样式的css样式值

/** *删除数组指定下标或指定对象 */ Array.prototype.remove=function(obj){ for(var i =0;i <this.length;i++){ var temp = this[i]; if(!isNaN(obj)){ temp=i; } if(temp == obj){ for(var j = i;j <this.length;j++){ this[j]=this[j+1]; } this.length = this.length-1; } } }

java 随机数不重复

package test; import java.util.HashSet; import java.util.Random; public class Snippet { /** * 随机指定范围内N个不重复的数 * 在初始化的无重复待选数组中随机产生一个数放入结果中, * 将待选数组被随机到的数,用待选数组(len-1)下标对应的数替换 * 然后从len-2里随机产生下一个随机数,如此类推 * @param  max  指定范围最大值 * @param  min  指定范围最小值 * @p

【HashSet:获取10个1至20的随机数,要求随机数不能重复】

package com.yjf.esupplier.common.test; import java.util.HashSet; import java.util.Random; /** * @author shusheng * @description 获取10个1至20的随机数,要求随机数不能重复 * @Email [email protected] * @date 2018/12/17 15:33 */ public class HashSetDemo { public static vo