mt_rand() 和 rand() 之间的区别
Difference between mt_rand() and rand()
关于速度,使用mt_rand($min, $max)
和rand($min, $max)
有什么区别?
PHP mt_rand()
上的手册指出:
which will produce random numbers four times faster than what the average libc rand() provides.
以下是两者的速度差异:-
mt_rand($min, $max)
是四 倍 [= =11=]
原因是,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 的结果 Ubuntu 11:
Darwin 5.5.19
0.038038969039917
0.033117055892944
Linux 5.3.6-13ubuntu3.10
0.031459093093872
0.031935214996338
如果这些措施是正确的,应该考虑其他地方提到的人工评论wrong/obsolete。
更新
由于 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
种子是什么,并用它预测下一个随机数。有一些工具可以做到这一点,所以 google 稍微测试一下。
rand
在其随机数 as demonstrated here 中相对快速地显示模式也存在问题。一个问题 mt_rand
似乎也解决得更好了。
mt_rand
使用了更好的随机化算法(Mersenne Twist),需要知道更多的随机数才能确定种子和速度更快。 这并不意味着 mt_rand
根据定义比 rand
快 ,这仅意味着生成的数字更快,并且似乎对函数的性能没有真正的影响,正如这里的其他答案所证明的那样。
不管怎样,看看 the mt_srand
and the srand
docs。我相信它们会包含更多信息
如果 mt_rand
的算法转化为性能的提高,那么这对您来说很好,但这是一个快乐的巧合。长话短说:
mt_rand
的引入是为了修复rand
!
中存在的问题
更新 (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()
.
这意味着从 7.1 版开始,两者之间没有实际区别,因为 rand
calls mt_rand
internally。
之前 PHP 7.1:
如果不是出于安全目的,使用 rand()
并不是一个坏习惯,我通常使用 rand()
(习惯?)。
如果您需要大量的随机数,您将需要 mt_rand
而不是 rand
。 mt_rand
的周期为 219937 − 1,远好于 rand
(232)。查看 this article 关于使用 rand
和 mt_rand
.
生成图形模式
Periodicity and entropy 是使用 mt_rand()
而不是 rand()
的唯一原因,而不是安全或速度改进。
在数学上 mt_rand
比 rand
多 entropy and a greater periodicity (219937−1 对比 232).
如果您需要一些随机数并且安全性不是问题,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);
}
PHP7.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()
possibly is the best solution, does its work (far better but slower? we need security over speed?) relying on openssl related issues。
rand()
nor mt_rand()
都不够安全:
Caution This 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.
有 PHP 个扩展,例如 random_compat
,但如果没有必要,我不建议使用它们。
从 PHP 7.1 开始,完全没有区别。 rand() 现在是 mt_rand() 的别名。
见http://php.net/manual/en/migration71.incompatible.php#migration71.incompatible.rand-srand-aliases
关于速度,使用mt_rand($min, $max)
和rand($min, $max)
有什么区别?
PHP mt_rand()
上的手册指出:
which will produce random numbers four times faster than what the average libc rand() provides.
以下是两者的速度差异:-mt_rand($min, $max)
是四 倍 [= =11=]
原因是,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 的结果 Ubuntu 11:
Darwin 5.5.19
0.038038969039917
0.033117055892944
Linux 5.3.6-13ubuntu3.10
0.031459093093872
0.031935214996338
如果这些措施是正确的,应该考虑其他地方提到的人工评论wrong/obsolete。
更新
由于 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
种子是什么,并用它预测下一个随机数。有一些工具可以做到这一点,所以 google 稍微测试一下。
rand
在其随机数 as demonstrated here 中相对快速地显示模式也存在问题。一个问题 mt_rand
似乎也解决得更好了。
mt_rand
使用了更好的随机化算法(Mersenne Twist),需要知道更多的随机数才能确定种子和速度更快。 这并不意味着 mt_rand
根据定义比 rand
快 ,这仅意味着生成的数字更快,并且似乎对函数的性能没有真正的影响,正如这里的其他答案所证明的那样。
不管怎样,看看 the mt_srand
and the srand
docs。我相信它们会包含更多信息
如果 mt_rand
的算法转化为性能的提高,那么这对您来说很好,但这是一个快乐的巧合。长话短说:
mt_rand
的引入是为了修复rand
!
中存在的问题
更新 (PHP 7.1):
rand()
andsrand()
have now been made aliases tomt_rand()
andmt_srand()
, respectively. This means that the output for the following functions have changes:rand()
,shuffle()
,str_shuffle()
, andarray_rand()
.
这意味着从 7.1 版开始,两者之间没有实际区别,因为 rand
calls mt_rand
internally。
之前 PHP 7.1:
如果不是出于安全目的,使用 rand()
并不是一个坏习惯,我通常使用 rand()
(习惯?)。
如果您需要大量的随机数,您将需要 mt_rand
而不是 rand
。 mt_rand
的周期为 219937 − 1,远好于 rand
(232)。查看 this article 关于使用 rand
和 mt_rand
.
Periodicity and entropy 是使用 mt_rand()
而不是 rand()
的唯一原因,而不是安全或速度改进。
在数学上 mt_rand
比 rand
多 entropy and a greater periodicity (219937−1 对比 232).
如果您需要一些随机数并且安全性不是问题,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);
}
PHP7.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()
possibly is the best solution, does its work (far better but slower? we need security over speed?) relying on openssl related issues。
rand()
nor mt_rand()
都不够安全:
Caution This 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()
, oropenssl_random_pseudo_bytes()
instead.
有 PHP 个扩展,例如 random_compat
,但如果没有必要,我不建议使用它们。
从 PHP 7.1 开始,完全没有区别。 rand() 现在是 mt_rand() 的别名。
见http://php.net/manual/en/migration71.incompatible.php#migration71.incompatible.rand-srand-aliases