Подтвердить что ты не робот

Разница между mt_rand() и rand()

В чем разница между использованием mt_rand($min, $max) и rand($min, $max) относительно скорости?

4b9b3361

Ответ 1

Update

Так как 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 релятививно быстро отображать шаблоны в своих случайных числах как показано здесь. Проблема mt_rand, похоже, тоже намного лучше.

mt_rand использует лучший алгоритм рандомизации (Mersenne Twist), который требует большего количества случайных чисел до того, как семя может быть определено и быстрее. Это не означает, что mt_rand по определению быстрее, чем rand, это означает, что способ генерации чисел быстрее и, по-видимому, не оказывает реального влияния на функцию как показали другие ответы здесь. В любом случае, посмотрите mt_srand и srand документы. Я уверен, что они будут содержать дополнительную информацию

Если алгоритм mt_rand преобразуется в увеличение производительности, то это здорово для вас, но это счастливое совпадение. TL; ТР:

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() (привычка?).

Если вам нужно огромное количество случайных чисел, вам понадобится mt_rand вместо rand. mt_rand имеет период 2 19937 - 1, намного лучше, чем rand (2 32). Взгляните на в этой статье о создании графического шаблона с использованием rand и mt_rand.

periodicity и entropy являются единственными причинами использования mt_rand() вместо rand(), а не улучшения безопасности или скорости.

Математически mt_rand имеет больше entropy и более высокий periodicity, чем rand (2 19937 -1 против 2 32).

Если вам нужны несколько случайных чисел, и безопасность не проблема, 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(), возможно, лучшее решение, делает его работу (гораздо лучше, но медленнее - нам нужна безопасность по скорости?) полагаясь на связанные с openssl проблемы.

Ни rand() и mt_rand() достаточно безопасны:

Предостережение Эта функция не генерирует криптографически безопасную значения и не должны использоваться для криптографических целей. Если тебе надо криптографически безопасное значение, рассмотрите возможность использования random_int(), random_bytes() или openssl_random_pseudo_bytes().

Существуют расширения PHP, такие как random_compat, но я не рекомендовал их использовать, если это не нужно.

Ответ 3

Руководство по PHP на mt_rand() утверждает, что оно:

который будет генерировать случайные числа в четыре раза быстрее, чем обеспечивает средний libc rand().

Ответ 5


Ниже приведена разница в скорости для обоих из них: -
mt_rand($min, $max) четыре раза быстрее по сравнению с rand($min, $max)

Причина в том, что rand($min, $max) использует генератор случайных чисел libc, а mt_rand($min, $max) использует Mersenne Twister, что в четыре раза быстрее.

Надеюсь, что это решит ваши сомнения.
Спасибо.

Ответ 6

Они кажутся равными по скорости:

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'ed Ubuntu 11:

Darwin 5.5.19
0.038038969039917
0.033117055892944

Linux 5.3.6-13ubuntu3.10
0.031459093093872
0.031935214996338

Если эти меры верны, комментарий к руководству, упомянутый в другом месте, должен считаться неправильным/устаревшим.