繁体   English   中英

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

[英]Difference between mt_rand() and rand()

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

更新

由于PHP 7.1 mt_rand完全取代了rand ,因此rand成为mt_rand的别名。 下面的答案集中在旧版本的两个函数之间的差异,以及引入mt_rand的原因。


速度不是mt_rand引入的原因!

rand函数在mt_rand之前存在,但它存在严重缺陷。 PRNG必须得到一些熵,一个数字,从中产生一系列随机数。 如果你打印出由rand()生成的十个数字的列表,如下所示:

for ($i=0;$i<10;++$i)
    echo rand(), PHP_EOL;

输出可以用来计算rand种子是什么,用它,你可以预测下一个随机数。 有一些工具可以做到这一点,所以谷歌稍微测试一下。

还有一个问题是rand相对较快地快速显示其随机数中的模式, 如此处所示 一个问题mt_rand似乎也解决了很多问题。

mt_rand使用更好的随机化算法(Mersenne Twist),这需要在确定种子之前知道更多随机数并且更快。 这并不意味着mt_rand根据定义比rand更快 ,这只意味着生成数字的方式更快,并且似乎对函数的性能没有实际影响,正如此处的其他答案所证明的那样。
无论哪种方式,请查看mt_srandsrand docs 我相信他们会包含更多信息

如果mt_rand的算法转化为性能提升,那么这对你来说很好,但这是一个快乐的巧合。 TL; TR:

引入mt_rand来解决rand中存在的问题!

更新(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 )。 看看这篇关于使用randmt_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);
}

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

在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

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


用于安全目的

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

rand()mt_rand()都不够安全

注意此函数不会生成加密安全值,也不应用于加密目的。 如果需要加密安全值,请考虑使用random_int()random_bytes()openssl_random_pseudo_bytes()

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

关于mt_rand() PHP手册说明:

这将产生比平均libc rand()提供的速度快四倍的随机数。

从PHP 7.1开始, 没有任何区别 rand()现在是mt_rand()的别名。

http://php.net/manual/en/migration71.incompatible.php#migration71.incompatible.rand-sr​​and-aliases

更多细节: https//wiki.php.net/rfc/rng_fixes


以下是两者的速度差异: -
mt_rand($min, $max)是快四倍相比, rand($min, $max)

原因是, rand($min, $max)使用libc随机数生成器,mt_rand($min, $max)使用Mersenne Twister ,速度快四倍。

希望它能解决你的疑问。
谢谢。

它们的速度似乎相等:

function timeit($times, $func) {
    $t = microtime(1);
    while($times--) $func();
    return microtime(1) - $t;
}

echo PHP_OS, " ", phpversion(), "\n";
echo timeit(100000, function() {    rand(0,1000); }), "\n";
echo timeit(100000, function() { mt_rand(0,1000); }), "\n";

OSX Mavericks和VirtualBox'ed Ubuntu 11的结果:

Darwin 5.5.19
0.038038969039917
0.033117055892944

Linux 5.3.6-13ubuntu3.10
0.031459093093872
0.031935214996338

如果这些措施是正确的,那么其他地方提到的手工评论应被视为错误/过时。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM