您现在的位置: 365建站网 > 365文章 > C# Random.Next 产生随机数的方法

C# Random.Next 产生随机数的方法

文章来源:365jz.com     点击数:1587    更新时间:2018-06-10 11:24   参与评论

.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毫秒做基础单位的时间数量单位)来产生随机数,还是存在合理性的。


</>code

  1. /// <summary>
  2.         /// 用随机数实现一件事情出现的概率是10%,另一件事情出现的概率是90%
  3.         /// </summary>
  4.         /// <param name="args"></param>
  5.         private static void Main(string[] args)
  6.         {
  7.             //string[] arr = { "10", "90", "90", "90", "90", "90", "90", "90", "90", "90" };
  8.             Random ran = new Random(unchecked((int)DateTime.Now.Ticks));
  9.             int num1 = 0;
  10.             int num2 = 0;
  11.             for (int i = 0; i < 100000; i++)
  12.             {
  13.                 int n = ran.Next(0, 10);
  14.                 //string str = arr[n];
  15.                 if (n == 0)
  16.                 {
  17.                     num1++;
  18.                 }
  19.                 else
  20.                 {
  21.                     num2++;
  22.                 }
  23.             }
  24.             Console.Write(num1 + "--" + num2);
  25.         }
  26.         /// <summary>
  27.         ///举例:用等差概率取0-99的整数,但让99的出现几率最大,98比99小一点,97比98小一点,0出现的几率最小
  28.         /// </summary>
  29.         /// <param name="number"></param>
  30.         /// <returns></returns>
  31.         private static int GetRandom(int number)
  32.         {
  33.             int maxNumber = number + 1;
  34.             int maxRange = ((1 + maxNumber) * maxNumber) / 2;
  35.             Random rd = new Random();
  36.             int randomNumber = Math.Abs(rd.Next() % maxRange);
  37.             int sum = 0;
  38.             for (int i = 0; i < maxNumber; i++)
  39.             {
  40.                 sum += (maxNumber - i);
  41.                 if (sum > randomNumber)
  42.                 {
  43.                     return i;
  44.                 }
  45.             }
  46.             return -1;
  47.         }


昨天网站被人DOS攻击,网站的同时连接数达到了1000多,我的程序是一个投票的程序,在投票之前需要做验证码认证,不过验证码是放在Cookie中的,这给了作弊者一个可乘之机。在作弊者发动大规模作弊攻击时,网站的验证码出现了很奇怪的现象,总是返回AAAA,也就是说Random.Next(int number)方法总是返回0了。这是怎么回事呢? 

通过google查出Random确有这个毛病,原因是Random本身是非线程安全的,而在Asp.net中是多线程环境,Random.Next方法在多线程环境下跑到一定时候,就会出现这种情况。 

他推荐使用RandomNumberGenerator类,我当时情急之中,直接使用了Guid.NewGuid().ToString(0,4)了。或者通过下面的类,编程线程安全的调用Random类的Next方法。

</>code

  1. class ThreadSafeRandom
  2. {
  3.     private static Random random = new Random();
  4.     public static int Next()
  5.     {
  6.        lock (random)
  7.        {
  8.            return random.Next();
  9.        }
  10.     }
  11. }


如对本文有疑问,请提交到交流论坛,广大热心网友会为你解答!! 点击进入论坛

发表评论 (1587人查看0条评论)
请自觉遵守互联网相关的政策法规,严禁发布色情、暴力、反动的言论。
昵称:
最新评论
------分隔线----------------------------

快速入口

· 365软件
· 杰创官网
· 建站工具
· 网站大全

其它栏目

· 建站教程
· 365学习

业务咨询

· 技术支持
· 服务时间:9:00-18:00
365建站网二维码

Powered by 365建站网 RSS地图 HTML地图

copyright © 2013-2024 版权所有 鄂ICP备17013400号