Генерация случайных чисел: от базовых до безопасных решений

Раздел: PHP программирование -> Числа в PHP

Основные подходы к генерации случайных чисел в PHP

Наиболее эффективное и безопасное решение для большинства задач — функция random_int(). Она гарантирует криптографически стойкие случайные целые числа в заданном диапазоне, используя системный источник энтропии. Для случаев, где безопасность не критична (например, игровая механика, не влияющая на безопасность), можно применять mt_rand() — она быстрее и имеет лучший период псевдослучайной последовательности.


// Криптостойкое случайное число от 1 до 100
echo random_int(1, 100);
  
74
  

// Быстрое небезопасное случайное число от 1 до 100
echo mt_rand(1, 100);
  
42
  

Типичная ошибка — использование rand() без аргументов, что даёт число от 0 до getrandmax(). При попытке получить число в нужном диапазоне через остаток от деления (rand() % 100) возникает смещение распределения из-за неравномерного остатка. Функции random_int() и mt_rand() решают эту проблему.

Как сгенерировать случайное целое число в заданном диапазоне?

Используйте random_int($min, $max) для безопасных целей или mt_rand($min, $max) для обычных.


$number = random_int(5, 15); // от 5 до 15 включительно
echo $number;
  
12
  

Ошибка: передача нецелых аргументов или min > max вызывает исключение (random_int) или предупреждение (mt_rand). Всегда проверяйте типы и корректность границ.

Как получить случайное число с плавающей точкой от 0 до 1?

Разделите результат mt_rand() на mt_getrandmax(). Для криптостойкости используйте random_int() с делением.


// Небезопасный вариант
$float = mt_rand() / mt_getrandmax();
echo $float;
  
0.473829104
  

// Безопасный вариант
$float = random_int(0, PHP_INT_MAX) / PHP_INT_MAX;
echo $float;
  
0.189234023
  

Проблема: при использовании PHP_INT_MAX как делителя возможно переполнение при умножении. Лучше использовать random_int(0, 1e12) / 1e12 для получения числа с ограниченной точностью.

Как перемешать массив случайным образом?

Функция shuffle() перемешивает массив на месте, используя внутренний генератор случайных чисел.


$cards = ['A', 'K', 'Q', 'J'];
shuffle($cards);
print_r($cards);
  
Array
(
    [0] => Q
    [1] => A
    [2] => J
    [3] => K
)
  

Ошибка: shuffle() использует тот же генератор, что и rand() — по умолчанию mt_rand(). Для криптостойкого перемешивания (например, в лотерее) применяйте array_rand() в сочетании с random_int() или специальную функцию.

Как получить случайный элемент из массива?

Функция array_rand() возвращает один или несколько случайных ключей массива. По умолчанию она использует mt_rand(), но можно передать random_int через коллбек.


$fruits = ['apple', 'banana', 'cherry'];
$key = array_rand($fruits);
echo $fruits[$key];
  
banana
  

Проблема: array_rand() не использует криптостойкий генератор. Для безопасного выбора (например, генерация токена) создайте собственный вызов с random_int().


$key = random_int(0, count($fruits) - 1);
echo $fruits[$key];
    

Расширенные примеры генерации случайных чисел

Создание случайного пароля заданной длины

Используйте random_bytes() для получения криптостойких байтов, затем закодируйте их в строку.

Пример

function generatePassword($length = 12) {
    $bytes = random_bytes(ceil($length * 3/4));
    return substr(base64_encode($bytes), 0, $length);
}
echo generatePassword(16);
  
A3xR9kLmN2Pq
  

Ошибка: использование base64_encode() может включать символы + и /, которые не подходят для паролей. Можно заменить их на безопасные символы с помощью strtr().

Генерация UUID v4 (случайный идентификатор)

Стандарт RFC 4122 требует 122 бита случайных данных. Реализуйте через random_bytes().

Пример

function uuidV4() {
    $data = random_bytes(16);
    $data[6] = chr(ord($data[6]) & 0x0f | 0x40);
    $data[8] = chr(ord($data[8]) & 0x3f | 0x80);
    return vsprintf('%s%s-%s-%s-%s-%s%s%s', str_split(bin2hex($data), 4));
}
echo uuidV4();
  
f47ac10b-58cc-4372-a567-0e02b2c3d479
  

Воспроизводимая последовательность случайных чисел (seed)

Функция mt_srand($seed) задаёт начальное состояние для mt_rand(), что полезно для тестирования.

Пример

mt_srand(42);
echo mt_rand(1, 100) . "\n";
echo mt_rand(1, 100) . "\n";
// Сброс seed для повторения
mt_srand(42);
echo mt_rand(1, 100) . "\n";
  
56
22
56
  

Проблема: mt_srand() не влияет на random_int() и random_bytes(). Для воспроизводимости криптостойких чисел используйте ручные алгоритмы (например, AES в режиме CTR с известным ключом).

Генерация случайного числа с нормальным распределением

Метод Бокса-Мюллера преобразует два равномерных случайных числа в нормально распределённые.

Пример

function gaussRandom($mean = 0, $stddev = 1) {
    $u1 = mt_rand() / mt_getrandmax();
    $u2 = mt_rand() / mt_getrandmax();
    $z = sqrt(-2 * log($u1)) * cos(2 * M_PI * $u2);
    return $mean + $z * $stddev;
}
echo gaussRandom(100, 15);
  
118.4723
  

Ошибка: если $u1 = 0, логарифм даст -INF. Добавьте минимальное значение, например max($u1, 1e-10).

Безопасное получение случайных байтов для криптографии

Функция random_bytes($length) возвращает строку сырых байтов. Используйте для создания ключей, соли, nonce.

Пример

$salt = random_bytes(16);
echo bin2hex($salt);
  
a1b2c3d4e5f6071829
  

Проблема: на некоторых системах (например, в изолированных окружениях) вызов random_bytes() может выбросить исключение из-за отсутствия источника энтропии. Обрабатывайте через try/catch.

- количество чисел php (количество чисел в php)
- Php следующее число (получение следующего числа в php)
- Php целое число (проверка целого числа в php)
- Php переменная число (переменная числа в php)
- Php получить число (получение числа в php)
- массив чисел php (массив чисел в php)
- Php число с точкой (число с плавающей точкой в php)
- Php сумма чисел (сумма чисел в php)
- Php преобразовать число (преобразование числа в php)
- Php большие числа (работа с большими числами в php)
- Php строку в число (преобразование строки в число в php)
- Php случайное число (генерация случайного числа в php)

Генерация случайного числа в PHP - comments

En
Php случайное число (php)