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

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

文章来源:365jz.com     点击数:352    更新时间: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毫秒做基础单位的时间数量单位)来产生随机数,还是存在合理性的。


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


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


发表评论 (352人查看0条评论)
请自觉遵守互联网相关的政策法规,严禁发布色情、暴力、反动的言论。
用户名: 验证码: 点击我更换图片
最新评论
------分隔线----------------------------