随机数生成器原理

以前常常会用到随机数,但是不知道其中的原理,今天在看《PHP经典实例》的时候,发现几个关于随机数的函数,于是想深入了解一下:

① rand(min, max)
② mt_rand(min, max)
③ srand(seed)
④ mt_srand(seed)

一、①和②

这两个使用的比较多,所以是比较容易理解

1、相同点

都是在[min, max]中产生一个随机数,并返回

2、不同点

两者实现方法不同,mt_rand 是基于 Mersenne Twister 算法实现的,相对于 rand 函数而言,mt_rand 更随机、性能更好,因此 通常使用 mt_rand 替换 rand

二、③和④

PHP官网是这样介绍两者的:

srand — 播下随机数发生器种子 (From Here)
mt_srand — 播下一个更好的随机数发生器种子 (From Here)

emmm...这什么玩意?
种子是啥?
不如动手写代码测试一下这两个蜜汁函数吧

1、测试

(1)测试代码1

mt_srand(222);
echo mt_rand();

(2)结果1

> php a.php 
1129637443
> php a.php
1129637443
> php a.php
1129637443

哇噢😯,amazing,三次执行的结果都是一样的,写个循环再测一下

(3)测试代码2

mt_srand(222);
for ($i = 10; $i > 0; $i--) {
    $random = mt_rand();
    echo $random, '  ';
}

(4)结果2

> php a.php
1129637443  456190486  1471707449  1162403591  1794596641  
1925135807  1403950198  1583402994  79504043  1458688054
> php a.php
1129637443  456190486  1471707449  1162403591  1794596641  
1925135807  1403950198  1583402994  79504043  1458688054
> php a.php
1129637443  456190486  1471707449  1162403591  1794596641  
1925135807  1403950198  1583402994  79504043  1458688054

虽然一次循环内部的数都不一样,但是每次生成的值都是一一对应相同的,玄学...

2、原理

然后搜索一下随机数发生器的实现原理,终于找到了答案:

其实通常情况下我们使用的随机数发生器产生的随机数都不是真正随机的,转念一想,好像有道理,毕竟计算机是按照固定的程序代码在执行的,通过固定不变的东西又怎么能产生随机的数呢?


那我们使用的随机数发生器是怎么产生随机数的呢?

(下文引用自知乎--王納米--的回答===传送门
大部分程序和语言中的随机数,确实都只是伪随机。是由可确定的函数(常用线性同余),通过一个种子(常用时钟),产生的。这意味着:如果知道了种子,或者已经产生的随机数,都可能获得接下来随机数序列的信息(可预测性)。


So, 种子就是随机数发生器生成随机数的依据,相同生成器采用相同种子生成的随机数都是一样的,即可预测性。因此,上面两个测试也就可以得到完美的解释了。我也了解了官网的这句话(ㄟ( ▔, ▔ )ㄏ): > 自 PHP 4.2.0 起,不再需要用 srand() 或 mt_srand() 给随机数发生器播种 ,因为现在是由系统自动完成的。

咱不用播种,只等收割(手动吃瓜...)


### 3、区别

我测试的结果是两个并没什么区别(测试方法:播种,然后循环获取10次随机数),不管是srand+rand、mt_srand+mt_rand、srand+mt_rand,还是mt_srand+rand,它们最后的结果都是一样的