Сгенерировать случайное число с предопределенной длиной PHP

Я пытаюсь создать функцию с помощью mt_rand (), чтобы создать действительно случайное число, так как rand () просто недостаточно.

проблема в том, что мне нужно предварительно определить длину числа, скажем, мне нужно 10-значное случайное число.

в любом случае, я возился, и вот что я придумал:

    function randomNumber($length) {
        $min = str_repeat(0, $length-1) . 1;
        $max = str_repeat(9, $length);
        return mt_rand($min, $max);   
    }

теоретически это должно работать (насколько я могу судить), но это не так. Длина полностью случайна, и она также выбрасывает отрицательный ценности.

какие идеи?

8 ответов


если у вас нет одной из этих квантово-статических штуковин, вы не можете получить действительно случайное число. Однако в ОС на базе Unix /dev/urandom работает для "большей случайности", если вам это действительно нужно.

в любом случае, если вы хотите n-значное число, это именно то, что вы должны получить: n отдельных цифр.

function randomNumber($length) {
    $result = '';

    for($i = 0; $i < $length; $i++) {
        $result .= mt_rand(0, 9);
    }

    return $result;
}

причина, по которой ваш существующий код не работает, заключается в том, что 0000...01 по-прежнему 1 to mt_rand, а также mt_randдиапазон не бесконечен. Отрицательное число целочисленные переполнения.


вот что я использую:

function random_number($length)
{
    return join('', array_map(function($value) { return $value == 1 ? mt_rand(1, 9) : mt_rand(0, 9); }, range(1, $length)));
}

одна линия, славная и простая! Число никогда не будет начинаться с 0 и позволяет 0 в любом другом месте.


коротко и ясно:

Я предполагаю только законные числа, а не строки, такие как 00010. Попробуйте использовать размер вашего номера, чтобы быть:

  $min = pow(10, $length - 1) ;
  $max = pow(10, $length) - 1;
  return mt_rand($min, $max);   

единственный, который не работает, когда длина равна 1, однозначное число " 0 " не будет возможным значением для возврата.


function randomNDigitNumber($digits)
{
  $returnString = mt_rand(1, 9);
  while (strlen($returnString) < $digits) {
    $returnString .= mt_rand(0, 9);
  }
  return $returnString;
}

первая строка гарантирует, что никакое "0" не предшествует любому числу, например значениям, таким как 012, 0598... будет отброшен, остальное легко


используйте это для строк определенной длины с буквами и цифрами. Проверенный.

protected function randomToken($length = 4, $result='') {

    for($i = 0; $i < $length; $i++) {

        $case = mt_rand(0, 1);
        switch($case){

            case 0:
                $data = mt_rand(0, 9);
                break;
            case 1:
                $alpha = range('a','z');
                $item = mt_rand(0, 25);

                $data = strtoupper($alpha[$item]);
                break;
        }

        $result .= $data;
    }

    return $result;
}

вы не должны начинать с длины, ограничивающей случайные числа. Скорее накопите достаточно длинный выход, а затем отрежьте его до нужной длины:

while (strlen($value) < $length) {
    $value .= str_pad(mt_rand(00000, 99999), 5, "0", STR_PAD_LEFT);
}
// as pairs of five were added before, eventually remove some again
return substr($value, 0, $length);

заполнение должно быть там, потому что даже нули генерируются случайным образом и должны быть сохранены.


function randomNumber($length) {
    $min = 1 . str_repeat(0, $length-1);
    $max = str_repeat(9, $length);
    return mt_rand($min, $max);   
}

у вас есть конкат 1 в неправильном месте, ваш диапазон-это для $length=2: {01,99} - иногда его 01-09, который представлен как 1-9 не 01-09. Просто начните с 10: {10,99} будет ваш выбор.


Как насчет этого:

function random($len)
{
    static $track = [];

    $min = 1 . str_repeat(0, $len - 1);
    $max = str_repeat(9, $len);
    $num = mt_rand($min, $max);

    // was this number generated before?
    if (in_array($num, $track))
    {
        // try again
        return random($len);
    }

    return $track[] = $num;
}

отслеживание сгенерированных чисел через статическую переменную (которая инициируется один раз) предотвратит генерирование одного и того же числа дважды, если вы не пройдете через весь диапазон, и в этом случае вы застряли в бесконечном цикле. Например:

for ($i = 0; $i < 10; $i++)
{
    random(1);
}