У меня есть это:
<?php $n = rand(1,1600); echo $n ?>
Я хочу исключить из случайных чисел, скажем, 234, 1578, 763, 1274 и другие числа. Как мне это сделать?
У меня есть это:
<?php $n = rand(1,1600); echo $n ?>
Я хочу исключить из случайных чисел, скажем, 234, 1578, 763, 1274 и другие числа. Как мне это сделать?
<?php
while( in_array( ($n = rand(1,1600)), array(234, 1578 ,763 , 1274) ) );
Попробуйте это
do {
$n = rand(1,1600);
} while(in_array($n, array(234, 1578 ,763 , 1274 ));
echo $n;
Проверьте, не номер, который вам не нужен, если он получает новое случайное число.
function getRandomNumber() {
do {
$n = mt_rand(1,1600);
} while(in_array($n, array(234,1578, 763, 1274)));
return $n;
}
Или избегайте создания циклов со случайным (возможно, бесконечным) временем выполнения:
/**
* Returns a random integer between $min and $max (inclusive) and
* excludes integers in $exarr, returns false if no such number
* exists.
*
* $exarr is assumed to be sorted in increasing order and each
* element should be unique.
*/
function random_exclude($min, $max, $exarr = array()) {
if ($max - count($exarr) < $min) {
return false;
}
// $pos is the position that the random number will take
// of all allowed positions
$pos = rand(0, $max - $min - count($exarr));
// $num being the random number
$num = $min;
// while $pos > 0, step to the next position
// and decrease if the next position is available
for ($i = 0; $i < count($exarr); $i += 1) {
// if $num is on an excluded position, skip it
if ($num == $exarr[$i]) {
$num += 1;
continue;
}
$dif = $exarr[$i] - $num;
// if the position is after the next excluded number,
// go to the next excluded number
if ($pos >= $dif) {
$num += $dif;
// -1 because we're now at an excluded position
$pos -= $dif - 1;
} else {
// otherwise, return the free position
return $num + $pos;
}
}
// return the number plus the open positions we still had to go
return $num + $pos;
}
Эта функция выбирает случайную позицию и проходит массив исключений, чтобы найти свободную позицию. Время работы зависит от количества номеров, которые нужно исключить. Если вы хотите исключить определенные диапазоны, вы можете адаптировать алгоритм, чтобы принять это во внимание.
Всегда используйте криптографически стойкие алгоритмы для генерации случайных чисел:
/**
* @param int $from From number
* @param int $to To number
* @param array $excluded Additionally exclude numbers
* @return int
*/
function randomNumber($from, $to, array $excluded = [])
{
$func = function_exists('random_int') ? 'random_int' : 'mt_rand';
do {
$number = $func($from, $to);
} while (in_array($number, $excluded, true));
return $number;
}
var_dump(randomNumber(1, 100));
var_dump(randomNumber(1, 10, [5, 6, 7, 8]));
var_dump(randomNumber(1, 100, range(10, 90)));
Я бы также рекомендовал использовать библиотеку paragonie/random_compat для совместимости в случае использования нескольких версий PHP.
Вы можете создать массив с действительными числами.
Затем ваше генерирование случайных чисел должно вернуть индекс в этот массив.
Если у вас слишком много номеров для исключения, проще и быстрее просто повторить попытку, если вы найдете нежелательный номер:
$n = 0;
while (in_array($n, array(0, 234, 1578 ,763 , 1274))) {
$n = rand(1,1600);
}
echo $n;
Другое решение для этого может быть следующим:
function random_number($min, $max, $exclude)
{
$number = rand($min, $max);
if(in_array($number, $exclude))
{
random_number($min, $max, $exclude);
} else {
return $number;
}
}
$number = random_number(1,10, [2,5,6]);
По мере того, как объем целых чисел, занесенных в "черный список", приближается к объему всего диапазона целых чисел, становится все более убедительным прислушиваться к совету @regenschein.
Не итеративный подход может выглядеть так:
$range = range(1, 1600);
$blacklist = [234, 1578, 763, 1274]; // 4 blacklisted versus 1600 full range is NOT compelling
$valids = array_diff($range, $blacklist);
echo array_values($valids)[rand(0, count($valids) - 1)];
// or
echo $valids[array_rand($valids)];
// the two approaches use different randomizers
Или, если вы будете так же счастливы, вы можете сделать:
$blacklist = [234, 1578, 763, 1274];
$range = range(1, 1600);
$valids = array_diff($range, $blacklist);
shuffle($valids);
echo $valids[0];
* Обратите внимание, что array_diff()
особенно array_diff()
если вы хотите передать несколько массивов черного списка - просто разделите их запятыми.
Например:
var_export($valids = array_diff(range(1, 100), range(5, 50), range(61, 99), [55]));
Выход:
array (
0 => 1,
1 => 2,
2 => 3,
3 => 4,
50 => 51,
51 => 52,
52 => 53,
53 => 54,
55 => 56,
56 => 57,
57 => 58,
58 => 59,
59 => 60,
99 => 100,
)
Я знаю, что это немного устарело, но я думаю, что операция пытается перетасовать целые числа. Если так, то следующий метод лучше
$array = array(1,2,3,4,5,6,7);
shuffle($array);
Этот код рандомизирует порядок точных элементов массива без повторения и возвращает результат внутри самого массива.