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

Создание UNIQUE случайных чисел в пределах диапазона - PHP

Мне нужно генерировать случайные УНИКАЛЬНЫЕ числа в пределах диапазона? как это сделать?

i может генерировать число randoms на

generator:
$arr=array();
$x=rand($min,$max);
$len=count($arr);
$flag = 0;
for($i=0;$i<$len;$i++)
{
 if ($flag == 1)
   goto generator;
 if ($x == $arr[$i])
   $flag = 1;
}
$arr[$index] = $x;
$index++; 
goto generator;

Я знаю, что этот код плохой, поэтому мне нужен лучший оптимизированный код моей версии! помощь!

Пример: если мне нужно сгенерировать 3 числа в пределах от 1 до 15, они должны быть похожими на 5, 9, 1, но не 3,1,2 [с в 1 - 3 (числа, которые я хочу создать)]

4b9b3361

Ответ 1

Массив с диапазоном чисел в случайном порядке:

$numbers = range(1, 20);
shuffle($numbers);

Обернутая функция:

function UniqueRandomNumbersWithinRange($min, $max, $quantity) {
    $numbers = range($min, $max);
    shuffle($numbers);
    return array_slice($numbers, 0, $quantity);
}

Пример:

<?php
print_r( UniqueRandomNumbersWithinRange(0,25,5) );
?>

Результат:

 Array
(
    [0] => 14
    [1] => 16
    [2] => 17
    [3] => 20
    [4] => 1
)

Ответ 2

$len = 10;   // total number of numbers
$min = 100;  // minimum
$max = 999;  // maximum
$range = []; // initialize array
foreach (range(0, $len - 1) as $i) {
    while(in_array($num = mt_rand($min, $max), $range));
    $range[] = $num;
}
print_r($range);

Мне было интересно увидеть, как принятый ответ складывается против моего. Полезно отметить, что гибрид обоих может быть выгодным; на самом деле функция, которая условно использует тот или иной в зависимости от определенных значений:

# The accepted answer
function randRange1($min, $max, $count)
{
    $numbers = range($min, $max);
    shuffle($numbers);
    return array_slice($numbers, 0, $count);
}

# My answer
function randRange2($min, $max, $count)
{
    $range = array();
    while ($i++ < $count) {
        while(in_array($num = mt_rand($min, $max), $range));
        $range[] = $num;
    }
    return $range;
}

echo 'randRange1: small range, high count' . PHP_EOL;
$time = microtime(true);
randRange1(0, 9999, 5000);
echo (microtime(true) - $time) . PHP_EOL . PHP_EOL;

echo 'randRange2: small range, high count' . PHP_EOL;
$time = microtime(true);
randRange2(0, 9999, 5000);
echo (microtime(true) - $time) . PHP_EOL . PHP_EOL;

echo 'randRange1: high range, small count' . PHP_EOL;
$time = microtime(true);
randRange1(0, 999999, 6);
echo (microtime(true) - $time) . PHP_EOL . PHP_EOL;

echo 'randRange2: high range, small count' . PHP_EOL;
$time = microtime(true);
randRange2(0, 999999, 6);
echo (microtime(true) - $time) . PHP_EOL . PHP_EOL;

Результаты:

randRange1: small range, high count
0.019910097122192

randRange2: small range, high count
1.5043621063232

randRange1: high range, small count
2.4722430706024

randRange2: high range, small count
0.0001051425933837

Если вы используете меньший диапазон и более высокий счет возвращаемых значений, принятый ответ, безусловно, оптимален; однако, как я и ожидал, большие диапазоны и меньшие подсчеты займет много времени с принятым ответом, так как он должен хранить все возможные значения в диапазоне. Вы даже рискуете выбросить крышку памяти PHP. Гибрид, который оценивает соотношение между диапазоном и количеством и условно выбирает генератор, был бы лучшим из обоих миров.

Ответ 3

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

function getDistinctRandomNumbers ($nb, $min, $max) {
    if ($max - $min + 1 < $nb)
        return false; // or throw an exception

    $res = array();
    do {
        $res[mt_rand($min, $max)] = 1;
    } while (count($res) !== $nb);
    return array_keys($res); 
}

Pro: Этот способ позволяет избежать использования in_array и не генерирует огромный массив. Таким образом, он быстро и сохраняет много памяти.

Минусы: когда скорость (диапазон/количество) уменьшается, скорость также уменьшается (но остается верной). При такой же скорости относительная скорость увеличивается с размером диапазона. (*)

(*) Я понимаю этот факт, так как для выбора (в частности, для первых шагов) больше свободных целых чисел, но если у кого-то есть математическая формула, описывающая это поведение, меня интересует, не стесняйтесь.

Заключение: лучшая "общая" функция, по-видимому, представляет собой комбинацию между этой функцией и функцией @Anne, которая более эффективна с небольшой скоростью. Эта функция должна переключаться между двумя способами, когда требуется определенное количество, и достигается скорость (диапазон/количество). Поэтому сложность/время теста, чтобы знать это, должны приниматься во внимание.

Ответ 4

Если вам нужны 5 случайных чисел от 1 до 15, вы должны сделать:

var_dump(getRandomNumbers(1, 15, 5));

function getRandomNumbers($min, $max, $count)
{
    if ($count > (($max - $min)+1))
    {
        return false;
    }
    $values = range($min, $max);
    shuffle($values);
    return array_slice($values,0, $count);
}

Он вернет false, если вы укажете значение счета больше, чем возможный диапазон чисел.

Ответ 5

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

Что-то вроде этого:

$arr = array();

for ($i=1;$i<=101;$i++) {
    $arr[] = $i;
}

shuffle($arr);

print_r($arr);

Результат будет выглядеть примерно так:

Array
(
    [0] => 16
    [1] => 93
    [2] => 46
    [3] => 55
    [4] => 18
    [5] => 63
    [6] => 19
    [7] => 91
    [8] => 99
    [9] => 14
    [10] => 45
    [11] => 68
    [12] => 61
    [13] => 86
    [14] => 64
    [15] => 17
    [16] => 27
    [17] => 35
    [18] => 87
    [19] => 10
    [20] => 95
    [21] => 43
    [22] => 51
    [23] => 92
    [24] => 22
    [25] => 58
    [26] => 71
    [27] => 13
    [28] => 66
    [29] => 53
    [30] => 49
    [31] => 78
    [32] => 69
    [33] => 1
    [34] => 42
    [35] => 47
    [36] => 26
    [37] => 76
    [38] => 70
    [39] => 100
    [40] => 57
    [41] => 2
    [42] => 23
    [43] => 15
    [44] => 96
    [45] => 48
    [46] => 29
    [47] => 81
    [48] => 4
    [49] => 33
    [50] => 79
    [51] => 84
    [52] => 80
    [53] => 101
    [54] => 88
    [55] => 90
    [56] => 56
    [57] => 62
    [58] => 65
    [59] => 38
    [60] => 67
    [61] => 74
    [62] => 37
    [63] => 60
    [64] => 21
    [65] => 89
    [66] => 3
    [67] => 32
    [68] => 25
    [69] => 52
    [70] => 50
    [71] => 20
    [72] => 12
    [73] => 7
    [74] => 54
    [75] => 36
    [76] => 28
    [77] => 97
    [78] => 94
    [79] => 41
    [80] => 72
    [81] => 40
    [82] => 83
    [83] => 30
    [84] => 34
    [85] => 39
    [86] => 6
    [87] => 98
    [88] => 8
    [89] => 24
    [90] => 5
    [91] => 11
    [92] => 73
    [93] => 44
    [94] => 85
    [95] => 82
    [96] => 75
    [97] => 31
    [98] => 77
    [99] => 9
    [100] => 59
)

Ответ 6

Вы можете попробовать следующий код:

function unique_randoms($min, $max, $count) {

 $arr = array();
 while(count($arr) < $count){
      $tmp =mt_rand($min,$max);
      if(!in_array($tmp, $arr)){
         $arr[] = $tmp;
      }
 }
return $arr;
}

Ответ 7

Получить случайное число. Он уже хранится в массиве? Если нет, сохраните его. Если да, тогда перейдите к другому случайному числу и повторите.

Ответ 8

Я думаю, что это, вероятно, не проблема для большинства, но я пытался ее решить. Я думаю, что у меня довольно приличное решение. В случае, если кто-то еще наткнется на эту проблему.

function randomNums($gen, $trim, $low, $high)
{
    $results_to_gen = $gen;
    $low_range      = $low;
    $high_range     = $high;
    $trim_results_to= $trim;

    $items = array();
    $results = range( 1, $results_to_gen);
    $i = 1;

    foreach($results as $result)
    {
        $result = mt_rand( $low_range, $high_range);
        $items[] = $result;

    }


    $unique = array_unique( $items, SORT_NUMERIC);
    $countem = count( $unique);
    $unique_counted = $countem -$trim_results_to;

    $sum = array_slice($unique, $unique_counted);


    foreach ($sum as $key)
    {
        $output = $i++.' : '.$key.'<br>';
        echo $output;
    }

}

randomNums (1100, 1000, 890000, 899999);

Ответ 9

Вероятно, это решит вашу проблему:

<?php print_r(array_rand(range(1,50), 5)); ?>

Ответ 10

Вот как я это сделаю.

$randnum1 = mt_rand(1,20);

$nomatch = 0;

while($nomatch == 0){

$randnum2 = mt_rand(1,20);

if($randnum2 != $randnum1){

$nomatch = 1;

}

}

$nomatch = 0;

while($nomatch == 0){

$randnum3 = mt_rand(1,20);

if(($randnum3 != $randnum1)and($randnum3 != $randnum2)){

$nomatch = 1;

}

}

Затем вы можете повторить результаты, чтобы проверить

echo "Random numbers are " . $randnum1 . "," . $randnum2 . ", and " . $randnum3 . "\n";

Ответ 11

Метод "тасования" имеет ОСНОВНОЕ ПОЛНОЕ. Когда цифры будут большими, перетасовать 3 миллиарда индексов немедленно вызовет ошибку CAUSE 500. Это лучшее решение для действительно больших чисел.

function getRandomNumbers($min, $max, $total) {
    $temp_arr = array();
    while(sizeof($temp_arr) < $total) $temp_arr[rand($min, $max)] = true;
    return $temp_arr;
}

Скажем, я хочу получить 10 уникальных случайных чисел от 1 миллиарда до 4 миллиардов.

$random_numbers = getRandomNumbers(1000000000,4000000000,10);

PS: Время выполнения: 0,027 микросекунды

Ответ 12

Просто используйте эту функцию и передайте счетчик числа, которое вы хотите сгенерировать

Код:

function randomFix($length)
{
    $random= "";

srand((double)microtime()*1000000);

$data = "AbcDE123IJKLMN67QRSTUVWXYZ";
$data .= "aBCdefghijklmn123opq45rs67tuv89wxyz";
$data .= "0FGH45OP89";

for($i = 0; $i < $length; $i++)
{
    $random .= substr($data, (rand()%(strlen($data))), 1);
}
return $random;}

Ответ 13

При создании приложения, в котором мне нужно было генерировать 30 000 уникальных чисел в более широком диапазоне, я смог сократить время обработки с 25 до 1,5 секунд, используя этот метод.

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

$count = 0;
$collectNumbers = [];
while ($count < 30000) {
for ($i = 0; $i < 60000; $i++) {

$rand = mt_rand(1, 100000);
$collectNumbers[] = $rand;

}
$unique = array_unique($collectNumbers);
$count = count($unique);
}

$finalArray = array_slice($unique, 0, 30000);

Это вернет 30000 уникальных номеров очень быстро. Использование значения итерации, равного удвоенному количеству чисел, которое вам нужно сгенерировать, может увеличить вероятность уникальных чисел на первой итерации... но независимо от того, сколько итераций потребуется, это даст результат быстрее, чем проверка вашего массива на повторяющиеся числа в петле.

Ответ 14

Лучший способ генерации уникального случайного числа -

<?php
     echo md5(uniqid(mt_rand(), true).microtime(true));
?>