计算机里的随机数是真的随机数吗?(C#实现)

在上一篇博客中写了验证码的代码——验证码及水印,验证码的原理就是产生随机数,然后把随机数写到动态图片中,在上边的代码中有个令我很费解

//生成起始序列值
int seekSeek = unchecked((int)DateTime.Now.Ticks);
Random seekRand = new Random(seekSeek);
int beginSeek = (int)seekRand.Next(0, Int32.MaxValue - length * 10000);
int[] seeks = new int[length];
for (int i = 0; i < length; i++)
{
    beginSeek += 10000;
    seeks[i] = beginSeek;
}

//生成随机数字
for (int i = 0; i < length; i++)
{
    Random rand = new Random(seeks[i]);
    int pownum = 1 * (int)Math.Pow(10, length);
    randMembers[i] = rand.Next(pownum, Int32.MaxValue);
}

为什么在生成随机数之间会有一个起始序列值,再生成随机数字?

在解答这个答案之间,我们先看下Random这个类中有什么,按F12转到Random类的定义

其中最重要的是Random的默认构造函数及有参(int Seed)的构造函数及Next方法,下面展开来看微软给他们的注释

默认构造函数public Pandom()

即Random random=new Random();

使用依赖于时间的默认种子值,简单来说在调用默认构造函数时,是根据系统的时间根据一定的算法(据说是线性同余法)生成随机数

看下边的代码

static void Main(string[] args)
{
    for (int i = 0; i < 10; i++)
    {
        Random random = new Random();
        for (int j = 0; j < 6; j++)//6个数字的随机序列
            Console.Write(string.Format("{0} ", random.Next()));
        Console.WriteLine();
    }
    Console.ReadKey();
}

运行结果:

从这个结果可以看出在调用Random类默认构造函数,根据当前系统时间产生的随机数序列是相同的,由此就可以证明,在计算机里不存在真正的随机数。

为了尽可能的避免这种情况的发生,于是就出现了有参的构造函数,即

Random random=new Random(int seed):使用指定的种子值。

而在程序中运用了时间间隔作为了种子值,就出现了咱们开头的代码

就是使用DateTime.Now.Ticks作为了种子值,而DateTime.Now.Ticks又表示什么呢?

DateTime.Ticks:表示0001 年 1 月 1 日午夜 12:00:00 以来所经历的 100 纳秒数,即Ticks的属性为100纳秒(1Ticks = 0.0001毫秒),而1秒等于1000毫秒

咱们试想一下,人点击刷新验证码中间间隔一般是超过一秒的,所以根据算法产生的数字在一定意义上是随机数,说明一下哈,是一定意义上,那么如果是计算机运行的程序中间间隔在1Ticks之内呢,那么结果很可能产生相同的数字,

所以,为了扩大这种时间间隔,第一步会根据时间间隔生成一个随机数序列(扩大了种子间隔),第二步根据扩大数据间隔的种子再作为种子进行产生随机数,于是出现了下面的代码

参考博客:

https://blog.csdn.net/weixin_34395205/article/details/86365944#commentsedit

生成随机数的算法

DateTime.Ticks属性解释

发布了156 篇原创文章 · 获赞 49 · 访问量 5万+

猜你喜欢

转载自blog.csdn.net/shang_0122/article/details/103268686