Лучший случайный генерирующий PHP
Я знаю, что просто с помощью rand()
предсказуемо, если вы знаете, что делаете, и имеете доступ к серверу.
У меня есть проект, который сильно зависит от выбора случайного числа, настолько непредсказуемого, насколько это возможно. Поэтому я ищу предложения, будь то другие встроенные функции или пользовательские функции, которые могут генерировать лучшее случайное число.
Я использовал это, чтобы сделать небольшой тест:
$i = 0;
while($i < 10000){
$rand = rand(0, 100);
if(!isset($array[$rand])){
$array[$rand] = 1;
} else {
$array[$rand]++;
}
sort($array);
$i++;
}
Я обнаружил, что результаты распределены равномерно, и число раз, которое генерируется каждое число, имеет странный характер.
6 ответов
Добавление, умножение или усечение плохого случайного источника даст вам плохой случайный результат. См. Введение в Случайность и Случайные Числа для объяснения.
Вы правы насчет функции PHP rand(). Смотрите на втором рисунке статистического анализа для наглядной иллюстрации. (Первая фигура поразительна, но она нарисована Скоттом Адамсом, а не нанесена с помощью rand()).
Одним из решений является использование настоящего генератора случайных чисел, такого как random.org. Еще один, если вы используете Linux/BSD/etc. использовать / dev / random. Если случайность критически важна, вам придется использовать аппаратный генератор случайных чисел.
У random.org есть API, доступ к которому вы можете получить через HTTP.
RANDOM.ORG - это сервис для работы со случайными числами, который генерирует случайность через атмосферный шум.
Я бы с осторожностью относился к впечатлению случайности: было много экспериментов, в которых люди выбирали менее случайное распределение. Кажется, что ум не очень хорош в создании или оценке случайности.
В Fourmilab есть хорошие статьи о случайности, включая еще один настоящий генератор случайных чисел. Может быть, вы могли бы получить случайные данные с обоих сайтов, так что если один не работает, у вас все еще есть другой.
Fourmilab также предоставляет тестовую программу для проверки случайности. Вы можете использовать его для проверки различных программ myRand().
Что касается вашей последней программы, если вы генерируете 10000 значений, почему бы вам не выбрать окончательное значение среди 10 тысяч? Вы ограничиваете себя подмножеством. Кроме того, он не будет работать, если ваши $min и $max превышают 10000.
В любом случае, случайность, которая вам нужна, зависит от вашего приложения. rand() подойдет для онлайн-игры, но не для криптографии (все, что не было тщательно протестировано статистическими программами, в любом случае не подойдет для криптографии). Ты будешь судьей!
Вариация @KG, используя миллисекунды с EPOCH в качестве начального числа для ранда?
Еще один способ получения случайных чисел, схожий по концепции с получением UUID
PHP версии 5.3 и выше
openssl_random_pseudo_bytes(...)
Или вы можете попробовать следующую библиотеку, используя RFC4122
В новом PHP7 есть функция, которая делает именно то, что вам нужно: она генерирует криптографически безопасные псевдослучайные целые числа.
int random_int ( int $min , int $max )
Генерирует криптографические случайные целые числа, которые подходят для использования в тех случаях, когда критичны непредвзятые результаты (т. Е. Тасование колоды покера)
Для более подробного объяснения о PRNG и CSPRNG (и их разнице), а также о том, почему ваш оригинальный подход на самом деле плохая идея, пожалуйста, прочитайте мой другой очень похожий ответ.