[英]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_srand
和srand
docs 。 我相信他们会包含更多信息
如果mt_rand
的算法转化为性能提升,那么这对你来说很好,但这是一个快乐的巧合。 TL; TR:
mt_rand
来解决rand
中存在的问题!
rand()
和srand()
现在分别成为mt_rand()
和mt_srand()
别名。 这意味着以下函数的输出有更改:rand()
,shuffle()
,str_shuffle()
和array_rand()
。
这意味着从版本7.1开始,两者之间没有实际区别,因为rand
内部调用mt_rand
。
如果不用于安全目的,使用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);
}
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-srand-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.