web-dev-qa-db-fra.com

Différence entre mt_Rand () et Rand ()

Quelle est la différence entre l'utilisation de mt_Rand($min, $max) et Rand($min, $max) sur la vitesse?

31
Thomas Rbt

Mise à jour

Depuis PHP 7.1 mt_Rand A complètement remplacé Rand et Rand a été créé un alias pour mt_Rand. La réponse ci-dessous se concentre sur les différences entre les deux fonctions pour les anciennes versions et les raisons de l'introduction de mt_Rand.


La vitesse n'est pas la raison pour laquelle mt_Rand A été introduit!

La fonction Rand existait bien avant mt_Rand, Mais elle était profondément défectueuse. A 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 nombres qui ont été 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 ce qu'était la graine Rand, et avec elle, vous pouvez prédire les prochains nombres aléatoires. Il existe des outils qui font cela, alors google un peu et testez-le.

Il y a aussi un problème avec Rand montrant rapidement des motifs dans ses nombres aléatoires comme démontré ici . Un problème mt_Rand Semble aussi beaucoup mieux résoudre.

mt_Rand Utilise un meilleur algorithme de randomisation (Mersenne Twist), qui nécessite de connaître plus de nombres aléatoires avant de déterminer la graine et est plus rapide. Cela ne signifie pas que mt_Rand Est, par définition, plus rapide que Rand est , 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 les performances de la fonction, comme l'ont démontré d'autres réponses ici.
Quoi qu'il en soit, jetez un œil à le mt_srand et le srand docs . Je suis sûr qu'ils contiendront plus d'informations

Si l'algorithme de mt_Rand Se traduit par une augmentation des performances, c'est parfait 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!

48
Elias Van Ootegem

Mise à jour (PHP 7.1):

Rand() et srand() sont désormais des alias pour mt_Rand() et mt_srand(), respectivement. Cela signifie que le les sorties des fonctions suivantes ont été modifiées: Rand(), shuffle(), str_shuffle() et array_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:

L'utilisation de Rand() n'est pas une mauvaise pratique si elle n'est pas utilisée à des fins de sécurité, j'utilise généralement Rand() (habitude?).

Si vous avez besoin d'une énorme quantité de nombres aléatoires, vous aurez besoin de mt_Rand À la place Rand. mt_Rand A une période de 219937 - 1, bien meilleur que Rand (232). Jetez un œil à cet article sur la génération de motifs graphiques en utilisant Rand et mt_Rand.

périodicité et entropie sont les seules raisons d'utiliser mt_Rand() à la place Rand() et non la sécurité ou des améliorations de vitesse.

Mathématiquement mt_Rand Ont plus entropie et plus périodicité que Rand (219937-1 contre 232).

Si vous avez besoin de quelques nombres aléatoires et que la sécurité n'est pas un problème, Rand fera le travail (obtenez un nombre aléatoire pour décider de lancer un processus de nettoyage).


Tester les améliorations de vitesse

En pratique, il n'y a pas beaucoup de différence de vitesse entre les deux fonctions (peut-être à cause de la surcharge du wrapper PHP?).

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 (machine plus lente):

$ 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 400% comme revendiqué.


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écurisé et openssl_random_pseudo_bytes() est probablement la meilleure solution, fait son travail (bien mieux mais plus lentement ? nous avons besoin de sécurité sur la vitesse?) en s'appuyant sur les problèmes liés à openssl .

Ni Rand() ni mt_Rand() ne sont suffisamment sûrs :

Attention Cette fonction ne génère pas de valeurs sécurisées cryptographiquement et ne doit pas être utilisée à des fins cryptographiques. Si vous avez besoin d'une valeur cryptographiquement sécurisée, pensez à utiliser à la place random_int(), random_bytes() ou openssl_random_pseudo_bytes().

Il y a PHP extensions comme random_compat , mais je ne recommande pas de les utiliser si ce n'est pas nécessaire.

24
OscarGarcia

Depuis PHP 7.1 il n'y a aucune différence . 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

1
Bell

Le manuel PHP sur mt_Rand() indique qu'il:

qui produira des nombres aléatoires quatre fois plus rapidement que ce que fournit la libc moyenne Rand ().

1
Forien