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

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

я могу генерировать число 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 (номера, которые я хочу сгенерировать)]

Solutions Collecting From Web of "Создание UNIQUE случайных чисел в пределах диапазона – PHP"

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

 $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 ) 
 $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. Гибрид, который оценивает соотношение между диапазоном и количеством, и условно выбирает генератор, будет лучшим из обоих миров.

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

 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, которая является более эффективной с небольшой скоростью. Эта функция должна переключаться между двумя способами, когда требуется определенное количество, и достигается скорость (диапазон / количество). Поэтому сложность / время теста, чтобы знать это, должны быть приняты во внимание.

Если вы хотите генерировать 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 ) 

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

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

 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; } 

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

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

 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);

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

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

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

 $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"; 

У метода «тасования» есть ОСНОВНОЕ ПОЛНОЕ. Когда цифры будут большими, перетасовать 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 микросекунды

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

Код:

 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;} 

Наилучшим способом генерации уникального случайного числа является

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