.net.Frameword中提供了一个专门产生随机数的类System.Random,此类默认情况下已被导入,编程过程中可以直接使用。我们知道,计算机并不能产生完全随机的数字,它生成的数字被称为伪随机数,它是以相同的概率从一组有限的数字中选取的,所选的数字并不具有完全的随机性,但就实用而言,其随机程度已经足够了。
是一个很常用的方法,但是一直没有注意到该方法的第二个参数(最大值),这个参数并不在随机数取值范围内。
简单举例:int theNum = ran.Next(1, 4); //theNum的取值范围是1~3,并不包括4. 一定要注意这个,今天要不是需要一个范围小的随机数,恐怕我一直都会犯这个错,一直以为这样是生成1~4的随机数呢。
下面内容摘自MSDN,原文:https://msdn.microsoft.com/zh-cn/library/2dx6wyd4(v=vs.110).aspx
Random.Next 方法 (Int32, Int32)
public virtual int Next( int minValue, int maxValue )
参数
minValue
类型:System.Int32
返回的随机数的下界(随机数可取该下界值)。
maxValue
类型:System.Int32
返回的随机数的上限(随机数不能取该上限值)。 maxValue 必须大于等于 minValue。
返回值
类型:System.Int32
大于等于 minValue 且小于 maxValue 的 32 位带符号整数,即:返回值的范围包括 minValue 但不包括maxValue。如果 minValue 等于 maxValue,则返回 minValue。
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毫秒做基础单位的时间数量单位)来产生随机数,还是存在合理性的。
/// <summary> /// 用随机数实现一件事情出现的概率是10%,另一件事情出现的概率是90% /// </summary> /// <param name="args"></param> private static void Main(string[] args) { //string[] arr = { "10", "90", "90", "90", "90", "90", "90", "90", "90", "90" }; Random ran = new Random(unchecked((int)DateTime.Now.Ticks)); int num1 = 0; int num2 = 0; for (int i = 0; i < 100000; i++) { int n = ran.Next(0, 10); //string str = arr[n]; if (n == 0) { num1++; } else { num2++; } } Console.Write(num1 + "--" + num2); } /// <summary> ///举例:用等差概率取0-99的整数,但让99的出现几率最大,98比99小一点,97比98小一点,0出现的几率最小 /// </summary> /// <param name="number"></param> /// <returns></returns> private static int GetRandom(int number) { int maxNumber = number + 1; int maxRange = ((1 + maxNumber) * maxNumber) / 2; Random rd = new Random(); int randomNumber = Math.Abs(rd.Next() % maxRange); int sum = 0; for (int i = 0; i < maxNumber; i++) { sum += (maxNumber - i); if (sum > randomNumber) { return i; } } return -1; }
昨天网站被人DOS攻击,网站的同时连接数达到了1000多,我的程序是一个投票的程序,在投票之前需要做验证码认证,不过验证码是放在Cookie中的,这给了作弊者一个可乘之机。在作弊者发动大规模作弊攻击时,网站的验证码出现了很奇怪的现象,总是返回AAAA,也就是说Random.Next(int number)方法总是返回0了。这是怎么回事呢?
通过google查出Random确有这个毛病,原因是Random本身是非线程安全的,而在Asp.net中是多线程环境,Random.Next方法在多线程环境下跑到一定时候,就会出现这种情况。
他推荐使用RandomNumberGenerator类,我当时情急之中,直接使用了Guid.NewGuid().ToString(0,4)了。或者通过下面的类,编程线程安全的调用Random类的Next方法。
class ThreadSafeRandom { private static Random random = new Random(); public static int Next() { lock (random) { return random.Next(); } } }
如对本文有疑问,请提交到交流论坛,广大热心网友会为你解答!! 点击进入论坛