我需要在一个范围内生成随机的UNIQUE数字吗?怎么做 ?
我可以生成随机数
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;
Run Code Online (Sandbox Code Playgroud)
我知道这段代码很糟糕,所以我需要一个更好的我的版本优化代码!救命 !
例如:如果我需要在1到15之间生成3个数字,它们应该像5,9,1但不是3,1,2 [在1-3中(我想要生成的数字)]
Ann*_*nne 123
具有随机顺序的数字范围的数组:
$numbers = range(1, 20);
shuffle($numbers);
Run Code Online (Sandbox Code Playgroud)
包裹功能:
function UniqueRandomNumbersWithinRange($min, $max, $quantity) {
$numbers = range($min, $max);
shuffle($numbers);
return array_slice($numbers, 0, $quantity);
}
Run Code Online (Sandbox Code Playgroud)
例:
<?php
print_r( UniqueRandomNumbersWithinRange(0,25,5) );
?>
Run Code Online (Sandbox Code Playgroud)
结果:
Array
(
[0] => 14
[1] => 16
[2] => 17
[3] => 20
[4] => 1
)
Run Code Online (Sandbox Code Playgroud)
Dan*_*ugg 16
$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);
Run Code Online (Sandbox Code Playgroud)
我很想知道接受的答案是如何与我的一致的.值得注意的是,两者的混合可能是有利的; 实际上是一个根据特定值有条件地使用一个或另一个的函数:
# 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;
Run Code Online (Sandbox Code Playgroud)
结果:
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
Run Code Online (Sandbox Code Playgroud)
如果您使用较小的范围和较高的返回值计数,则接受的答案肯定是最佳的; 然而正如我所预料的那样,较大的范围和较小的计数将在接受的答案中花费更长的时间,因为它必须存储范围内的每个可能的值.你甚至冒着吹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);
}
Run Code Online (Sandbox Code Playgroud)
Pro:这种方式避免了使用in_array并且不会生成庞大的数组.因此,它很快并且保留了大量内存.
缺点:当速率(范围/数量)减少时,速度也会降低(但保持正确).对于相同的速率,相对速度随着范围大小而增加.(*)
(*)我理解这个事实,因为有更多的自由整数可供选择(特别是第一步),但如果有人有描述这种行为的数学公式,我感兴趣,不要犹豫.
结论:最好的"一般"函数似乎是这个函数和@Anne函数之间的混合,它在一点点速率下效率更高.当需要一定数量并达到速率(范围/数量)时,此功能应在两种方式之间切换.因此,必须考虑到测试的复杂性/时间.