php mt_rand() 和 rand() 的区别

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/28760650/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-26 00:03:18  来源:igfitidea点击:

Difference between mt_rand() and rand()

phpperformanceoptimizationrandom

提问by Thomas Rbt

What is the difference between using mt_rand($min, $max)and rand($min, $max)about the speed?

usingmt_rand($min, $max)rand($min, $max)about speed 有什么区别?

回答by Elias Van Ootegem

Update

更新

Since PHP 7.1 mt_randhas superseded randcompletely, and randwas made an alias for mt_rand. The answer below focuses on the differences between the two functions for older versions, and the reasons for introducing mt_rand.

由于 PHP 7.1mt_randrand完全取代,并rand成为mt_rand. 下面的回答主要针对旧版本的两个函数的区别,以及引入mt_rand.



Speed was not why mt_randwas introduced!

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

The randfunction existed way before mt_rand, but it was deeply flawed. A PRNG must get some entropy, a number from which it generates a sequence of random numbers. If you print out a list of ten numbers that were generated by rand()like so:

rand功能以前存在mt_rand,但存在严重缺陷。PRNG 必须获得一些熵,即生成随机数序列的数字。如果您打印出由rand()如下生成的十个数字的列表:

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

The output can be used to work out what the randseed was, and with it, you can predict the next random numbers. There are tools out there that do this, so google a bit and test it.

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

There's also an issue with randrelativily quickly showing patterns in its random numbers as demonstrated here. A problem mt_randseems to solve a lot better, too.

还有有问题randrelativily迅速显示在它的随机数的图案作为这里展示。一个问题mt_rand似乎也能更好地解决。

mt_randuses a better randomization algorithm (Mersenne Twist), which requires more random numbers to be known before the seed can be determined andis faster. This does not mean that mt_randis, by definition, faster than randis, this only means that the way the numbers are generated is faster, and appears to have no real impact on the function's performance, as other answers here have demonstrated.
Either way, have a look at the mt_srandand the sranddocs. I'm sure they'll contain some more info

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

If mt_rand's algorithm translates in an increase in performance, then that's great for you, but it's a happy coincidence. TL;TR:

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

mt_randwas introduced to fix the problems that exist in rand!

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

回答by OscarGarcia

Update (PHP 7.1):

更新(PHP 7.1):

rand()and srand()have now been made aliases to mt_rand()and mt_srand(), respectively.This means that the output for the following functions have changes: rand(), shuffle(), str_shuffle(), and array_rand().

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

That means that since version 7.1 there is no practical difference between both of them because randcalls mt_randinternally.

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



Before PHP 7.1:

PHP 7.1 之前:

Using rand()is not a bad practice if it not used for security purposes, I'm usually using rand()(habit?).

rand()如果不用于安全目的,使用并不是一个坏习惯,我通常使用rand()(习惯?)。

If you need an enormous amount of random numbers you will need mt_randinstead rand. mt_randhas a period of 219937? 1, far better than rand(232). Take a look to this articleabout graphical pattern generation using randand mt_rand.

如果你需要的随机数的大量,您将需要mt_rand代替randmt_rand有一个时期 2 19937? 1,远好于rand(2 32)。看看这篇关于使用rand和生成图形模式的文章mt_rand

Periodicityand entropyare the only reasons for using mt_rand()instead rand()and not security or speed improvements.

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

Mathematically mt_randhave more entropyand a greater periodicitythan rand(219937?1 vs. 232).

在数学上比(2 19937?1 vs. 2 32)mt_rand具有更多的和更大的周期性rand

If you need a few random numbers and security is not a problem, randwill do the job (get a random number to decide firing a cleanup process).

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



Testing speed improvements

测试速度提升

In practice there is not much difference in speed between the two functions (maybe because PHP?C wrapper overhead?).

实际上,这两个函数之间的速度没有太大差异(可能是因为 PHP?C 包装器开销?)。

PHP test code:

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);
}

Tests in PHP 7.0.19:

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

Tests in PHP 5.4.45 (slower machine):

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

Only 6-9% and not 400% as claimed.

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



Using for security purposes

用于安全目的

But if your application needs a lot of entropy because security issues, you'll need a more secure way and openssl_random_pseudo_bytes()possibly is the best solution, does its work (far better but slower? we need security over speed?) relying on openssl related issues.

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

Neither rand()nor mt_rand()are safe enough:

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

CautionThis function does not generate cryptographically secure values, and should not be used for cryptographic purposes. If you need a cryptographically secure value, consider using random_int(), random_bytes(), or openssl_random_pseudo_bytes()instead.

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

There is PHP extensions like random_compat, but I didn't recommend using them if it not necessary.

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

回答by Bell

As of PHP 7.1 there is no difference at all. rand() is now an alias for mt_rand().

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

See http://php.net/manual/en/migration71.incompatible.php#migration71.incompatible.rand-srand-aliases

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

And more details: https://wiki.php.net/rfc/rng_fixes

以及更多详细信息:https: //wiki.php.net/rfc/rng_fixes

回答by Forien

PHP Manual on mt_rand()states that it:

PHP 手册上mt_rand()指出:

which will produce random numbers four times faster than what the average libc rand() provides.

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

回答by PHP Team


Following is the difference in speed for both of them :-
mt_rand($min, $max)is fourtimes faster as compared to rand($min, $max)

The reason is that,rand($min, $max)uses libc random number generatorwhile mt_rand($min, $max)uses Mersenne Twisterwhich is four times faster.

Hope it will solve your doubt.
Thanks.


以下是他们两人的速度差异: -
mt_rand($min, $max)4比快倍rand($min, $max)

的原因在于,rand($min, $max)使用 libc的随机数生成器,同时mt_rand($min, $max)使用梅森倍捻机是快四倍。

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

回答by georg

They appear to be equal in speed:

它们的速度似乎相等:

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";

Results for OSX Mavericks and VirtualBox'ed Ubuntu 11:

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

Darwin 5.5.19
0.038038969039917
0.033117055892944

Linux 5.3.6-13ubuntu3.10
0.031459093093872
0.031935214996338

If these measures are correct, the manual comment mentioned elsewhere should be considered wrong/obsolete.

如果这些措施是正确的,那么其他地方提到的手动注释应该被认为是错误的/过时的。