mt_rand()和rand()之间的区别

Tho*_*Rbt 34 php random optimization performance

使用mt_rand($min, $max)rand($min, $max)速度有什么区别?

Eli*_*gem 50

更新

由于PHP 7.1 mt_randrand完全取代,rand因此成为了别名mt_rand.下面的答案着重于旧版本的两个功能之间的差异,以及引入的原因mt_rand.


速度不是为什么mt_rand被引入!

这个rand功能以前存在过mt_rand,但它存在严重缺陷.PRNG必须得到一些熵,一个数字,从中产生一系列随机数.如果您打印出由rand()这样生成的十个数字的列表:

for ($i=0;$i<10;++$i)
    echo rand(), PHP_EOL;
Run Code Online (Sandbox Code Playgroud)

输出可以用来计算rand种子的含量,用它可以预测下一个随机数.有一些工具可以做到这一点,所以谷歌稍微测试一下.

还有一个问题是rand相对快速地显示其随机数中的模式,如此处所示.一个问题mt_rand似乎也解决得更好.

mt_rand使用更好的随机化算法(Mersenne Twist),这需要在确定种子之前知道更多随机数并且更快.这并不意味着mt_rand,顾名思义,速度比rand,这仅仅意味着产生的数字方式速度更快,而且似乎对函数的性能没有实质影响,因为这里其他的答案已经证明.
无论哪种方式,看看mt_srandsrand文档.我相信他们会包含更多信息

如果mt_rand算法的性能提高,那么这对你来说很好,但这是一个幸福的巧合.TL; TR:

mt_rand被介绍来解决存在的问题rand!

  • @PEMapModder答案写于〜2年前,在`rand`成为别名之前.WRT内容:它的主要重点是解释最初引入的_why_`mt_rand`(仍然是相关的).为了完整起见,我将添加一个更新,声明`rand`现在是别名.除此之外,所提供的信息仍然是正确的IMO (2认同)

Osc*_*cia 26

更新(PHP 7.1):

rand()并且srand()现在已分别为mt_rand()mt_srand().这意味着,输出用于以下功能有变化:rand(),shuffle(),str_shuffle(),和array_rand().

这意味着从版本7.1开始,两者之间没有实际区别,因为内部rand调用mt_rand.


在PHP 7.1之前:

rand()如果不用于安全目的,使用并不是一种不好的做法,我通常使用rand()(习惯?).

如果您需要大量随机数,则需要mt_rand使用rand.mt_rand期限为2 19937 - 1,远远优于rand(2 32).看看这篇关于使用rand和生成图形模式的文章mt_rand.

周期性是使用mt_rand()rand()不是安全性或速度改进的唯一原因.

在数学上mt_rand有更多的和更大的周期性大于rand(2 19937 -1对2 32).

如果您需要一些随机数并且安全性不是问题,则rand可以完成工作(获取一个随机数来决定启动清理过程).


测试速度的提高

在实践中,两个函数之间的速度差别不大(可能是因为PHP⇔C包装器开销?).

PHP测试代码:

<?php
for ($c = 0; $c < 3; $c++) {
  $start = microtime(true);
  $sum = 0.0;
  for ($i = 0; $i < 100000000; $i++) {
    $sum += rand();
  }
  printf('[rand %d] Time: %.3f s%s', $c, microtime(true) - $start, PHP_EOL);
}
for ($c = 0; $c < 3; $c++) {
  $start = microtime(true);
  $sum = 0.0;
  for ($i = 0; $i < 100000000; $i++) {
    $sum += mt_rand();
  }
  printf('[mt_rand %d] Time: %.3f s%s', $c, microtime(true) - $start, PHP_EOL);
}
Run Code Online (Sandbox Code Playgroud)

PHP 7.0.19中的测试:

$ php timing.php
[rand 0] Time: 4.658 s
[rand 1] Time: 4.664 s
[rand 2] Time: 4.654 s
[mt_rand 0] Time: 4.267 s
[mt_rand 1] Time: 4.255 s
[mt_rand 2] Time: 4.261 s
Run Code Online (Sandbox Code Playgroud)

在PHP 5.4.45中测试(较慢的机器):

$ php timing.php
[rand 0] Time: 10.862 s
[rand 1] Time: 10.889 s
[rand 2] Time: 10.615 s
[mt_rand 0] Time: 10.948 s
[mt_rand 1] Time: 9.883 s
[mt_rand 2] Time: 10.190 s
Run Code Online (Sandbox Code Playgroud)

声称只有6-9%而不是400%.


用于安全目的

但是,如果您的应用程序需要大量的熵,因为安全问题,您需要一种更安全的方式,openssl_random_pseudo_bytes()可能是最好的解决方案,它的工作(更好但更慢?我们需要安全性超速?)依赖于openssl相关问题.

既不安全rand()也不mt_rand()安全:

注意此函数不会生成加密安全值,也不应用于加密目的.如果你需要一个加密的安全值,可以考虑使用random_int(), random_bytes()openssl_random_pseudo_bytes()代替.

有像这样的PHP扩展random_compat,但如果没有必要,我不建议使用它们.