Différence entre mt rand () Et rand()
Quelle est la différence entre utiliser mt_rand($min, $max)
et rand($min, $max)
à propos de la vitesse?
6 réponses
mise à Jour
depuis PHP 7.1 mt_rand
remplace rand
complètement, et rand
est devenu un alias pour mt_rand
. La réponse ci-dessous se concentre sur les différences entre les deux fonctions pour les versions plus anciennes, et les raisons pour introduire mt_rand
.
Vitesse n'était pas pourquoi mt_rand
a été introduit!
rand
la fonction existait bien avant mt_rand
, mais il était profondément imparfait. Un PRNG doit obtenir une entropie, un nombre à partir duquel il génère une séquence de nombres aléatoires. Si vous imprimez une liste de dix numéros générés par rand()
comme ceci:
for ($i=0;$i<10;++$i)
echo rand(), PHP_EOL;
La sortie peut être utilisée pour déterminer l' rand
seed était, et avec elle, vous pouvez prédire les nombres aléatoires suivants. Il y a des outils là-bas qui font cela, alors google un peu et le tester.
Il y a aussi un problème avec rand
relativement rapidement montrant des modèles dans ses nombres aléatoires comme démontré ici. Un problème mt_rand
semble résoudre beaucoup mieux, aussi.
mt_rand
utilise un meilleur algorithme de randomisation (Mersenne Twist), qui nécessite plus de nombres aléatoires à connaître avant que la graine puisse être déterminée et est plus rapide. Cela ne signifie pas que mt_rand
est, par définition, plus rapide que rand
, cela signifie seulement que la façon dont les nombres sont générés est plus rapide, et semble n'avoir aucun impact réel sur la performance de la fonction, comme d'autres réponses ici ont démontré.
De toute façon, jetez un coup d'oeil à mt_srand
et srand
docs. Je suis sûr qu'ils contiendront plus d'informations
Si mt_rand
'algorithme se traduit par une augmentation de la performance, alors que c'est bon pour vous, mais c'est une heureuse coïncidence. TL;TR:
mt_rand
a été introduit pour résoudre les problèmes qui existent dans rand
!
mise à Jour (PHP 7.1):
rand()
etsrand()
sont maintenant des pseudonymes demt_rand()
etmt_srand()
, respectivement. cela signifie que la sortie pour les fonctions suivantes a des modifications:rand()
,shuffle()
,str_shuffle()
etarray_rand()
.
cela signifie que depuis la version 7.1 il n'y a aucune différence pratique entre les deux parce que rand
appelle mt_rand
en interne.
Avant PHP 7.1:
en utilisant rand()
n'est pas une mauvaise idée si c'est pas utilisé pour des raisons de sécurité, je suis généralement à l'aide de rand()
(habitude?).
Si vous avez besoin d'une énorme quantité de nombres aléatoires, vous aurez besoin mt_rand
au lieu de rand
. mt_rand
a une période de 219937 - 1, beaucoup mieux que rand
paragraphe 2 32). Jetez un oeil à cet article à propos du motif graphique génération utilisant rand
et mt_rand
.
Périodicité et entropie sont les seules raisons d'utiliser mt_rand()
au lieu de rand()
et pas d'amélioration de la sécurité ou de la vitesse.
Mathématiquement mt_rand
plus entropie et un plus grand périodicitérand
paragraphe 219937 -1 vs. 2 32).
si vous avez besoin de quelques nombres aléatoires et la sécurité est pas un problème, rand
fera le travail (obtenir un nombre aléatoire pour décider de lancer un processus de nettoyage).
Tester les améliorations de la vitesse
dans la pratique, il n'y a pas beaucoup de différence de vitesse entre les deux fonctions (peut-être parce que PHP se charge de l'emballage?).
code de test 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 en 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 en PHP 5.4.45 (plus lent de la machine):
$ 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
seulement 6-9% et non pas 400% comme déclaré.
utilisation à des fins de sécurité
mais si votre application a besoin de beaucoup d'entropie en raison de problèmes de sécurité, vous aurez besoin d'un moyen plus sûr et openssl_random_pseudo_bytes()
peut-être la meilleure solution, fait son travail (beaucoup mieux mais plus lent? nous avons besoin de sécurité au-dessus de la vitesse?) en se basant sur les questions liées à openssl.
ni L'un ni l'autre rand()
ni mt_rand()
sont assez sécuritaires:
Attention Cette fonction ne génère pas cryptographique sécurisé valeurs, et ne devrait pas être utilisé à des fins cryptographiques. Si vous avez besoin d' une valeur cryptographique sécurisée, envisagez d'utiliser
random_int()
,random_bytes()
, ouopenssl_random_pseudo_bytes()
à la place.
il y a des extensions PHP comme random_compat
, mais je ne recommande pas de les utiliser si c'est pas nécessaire.
à partir de PHP 7.1 il y a pas de différence à tous. Rand () est maintenant un alias pour mt_rand ().
Voir http://php.net/manual/en/migration71.incompatible.php#migration71.incompatible.rand-srand-aliases
Et plus de détails: https://wiki.php.net/rfc/rng_fixes
Voici la différence de vitesse pour les deux: -mt_rand($min, $max)
quatre fois plus rapide que rand($min, $max)
La raison en est que,rand($min, $max)
libc générateur de nombre aléatoiremt_rand($min, $max)
Mersenne Twister qui est quatre fois plus rapide.
espérons que cela résoudra votre doute.
Merci.
Ils apparaissent à la même vitesse:
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";
résultats pour OSX Mavericks et Virtualbox'ed Ubuntu 11:
Darwin 5.5.19
0.038038969039917
0.033117055892944
Linux 5.3.6-13ubuntu3.10
0.031459093093872
0.031935214996338
si ces mesures sont correctes, le commentaire manuel mentionné ailleurs doit être considéré comme erroné/périmé.