mt_rand() 和兰特()之间的区别速度不是为什么被引入!mt_rand mt_rand引入是为了修复 中存在的问题!rand更新 (PHP 7.1):在 PHP 7.1 之前的版本:测试速度改进用于安全目的

2022-08-30 11:07:28

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


答案 1

更新

由于 PHP 7.1 已被完全取代,并成为 .下面的答案重点介绍旧版本的两个函数之间的差异,以及引入的原因。mt_randrandrandmt_randmt_rand


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

这个函数在很久以前就已经存在了,但它有很深的缺陷。PRNG必须获得一些熵,这是一个数字,从中它生成一个随机数序列。如果您打印出由以下方式生成的十个数字的列表:randmt_randrand()

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

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

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

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

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

mt_rand引入是为了修复 中存在的问题!rand


答案 2

更新 (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()

如果你需要大量的随机数,你将需要代替。 周期为 219937 − 1,远优于 (232)。请看这篇关于使用 和 生成图形模式的文章。mt_randrandmt_randrandrandmt_rand

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

在数学上比(219937−1 vs. 232)具有更多的和更大的周期性mt_randrand

如果你需要几个随机数并且安全性不是问题,就会做这项工作(获取一个随机数来决定触发清理过程)。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()可能是最佳解决方案,它的工作是否有效(要好得多但速度更快?我们需要安全性而不是速度?)依赖于opensl相关的问题

rand()mt_rand() 都不够安全

谨慎此函数不生成加密安全值,并且不应用于加密目的。如果需要加密安全的值,请考虑改用 、 或 。random_int()random_bytes()openssl_random_pseudo_bytes()

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


推荐