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

时间:2015-02-27 08:37:53

标签: php performance optimization random

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

6 个答案:

答案 0 :(得分:45)

更新

由于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还存在一个问题,即相对较快地快速显示其随机数as demonstrated here中的模式。问题mt_rand似乎也解决得更好。

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

如果mt_rand的算法在性能上有所提升,那么这对你来说很棒,但这是一个快乐的巧合。 TL; TR:

引入了

mt_rand来修复rand中存在的问题!

答案 1 :(得分:24)

更新(PHP 7.1):

  

rand() and srand() have now been made aliases to mt_rand() and mt_srand(), respectively.这意味着以下功能的输出有所变化:rand()shuffle()str_shuffle()array_rand()

这意味着自7.1版以来,两者之间没有实际区别,因为rand calls mt_rand internally


在PHP 7.1之前:

如果不将rand()用于安全目的,那么使用rand()通常不会使用mt_rand(习惯?)。

如果您需要大量随机数,则需要rand而不是mt_randrand的周期为2 19937 - 1,远远优于rand(2 32 )。使用mt_randmt_rand()了解有关图形模式生成的this article

Periodicityentropy是使用rand()代替mt_rand而不是安全或速度提升的唯一原因。

数学上rand的{​​{3}}多entropyperiodicityrand更高(2 19937 -1 vs. 2 32 < / SUP>)。

如果您需要一些随机数并且安全性不是问题,<?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⇔C包装器开销?)。

PHP测试代码:

$ 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 7.0.19中的测试:

$ 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

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

random_int()

只有6-9%,而不是400%。


出于安全目的使用

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

rand() nor mt_rand()都不够安全

  

警告此功能不会生成加密安全   值,不应用于加密目的。如果你需要   加密安全值,请考虑使用random_bytes(),   openssl_random_pseudo_bytes(),或{{1}}。

random_compat之类的PHP扩展程序,但如果没有必要,我建议不要使用它们。

答案 2 :(得分:1)

mt_rand()上的PHP手册指出:

  

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

答案 3 :(得分:1)

从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

答案 4 :(得分:-1)

以下是两者的速度差异: - 与mt_rand($min, $max)相比,rand($min, $max) 快<4> >
原因是,rand($min, $max)使用 libc随机数生成器,而mt_rand($min, $max)使用 Mersenne Twister ,速度提高了四倍。<希望它能解决你的疑问。
谢谢。

答案 5 :(得分:-1)

它们的速度似乎相同:

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

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