我需要生成4个不同的随机数,给定范围。像这样:
define('min', 3000);
define('range', 6000);
define('diff', 200);
$array[0] = rand(min ,min + range);
$array[1] = rand(min ,min + range);
while(abs($array[0]-$array[1])<diff)
$array[0] = rand(min ,min + range);
$array[2] = rand(min ,min + range);
while((abs($array[2]-$array[0])<diff)
||(abs($array[2]-$array[1])<diff))
$array[2] = rand(min ,min + range);
$array[3] =rand(min ,min + range);
while((abs($array[3]-$array[0])<diff)
||(abs($array[3]-$array[1])<diff)
||(abs($array[3]-$array[2])<diff))
$array[3] = rand(min ,min + range);
有没有办法优化这个算法?
答案 0 :(得分:2)
首先,您可能希望声明在相同的间隔中需要四个随机数,但彼此之间的距离最小(如代码所示)。您当前的方法涉及循环,可能无限期,但可能只是一段时间,直到达到这些数字。
只要您只需要四个随机数,如果您这样做就没那么重要了。它可以更一般地编写,允许绘制更多数字的自然扩展,但这不一定会使它更快,即使对于四个数字。
假设你想要一个时间上限(你当前的代码只提供了一些概率),这里有一个算法可以工作(只要间隔足够大):画一个随机数 N 并创建两个间隔分区,一个用于低于 N 的有效后续数字,另一个用于高于 N 的有效后续数字。对于每个后续随机数,随机选择一个可用分区并以相同方式继续。
如果忽略count($intervals)
所花费的时间(可能需要O(1),但它会变得更加丑陋),这将在O( $ n )中运行。我不能说这个算法产生的数字与初始算法的概率分布相同。有一点表明概率分布存在偏差:分区是随机选择的,权重相等,而不是基于区间的大小。
<?php
function random_interval($n, $min, $max, $distance) {
$result = array();
$intervals = array(array($min, $max));
while ($n-- > 0 && count($intervals) > 0) {
// find a random, valid interval
$i = array_rand($intervals);
// extract this interval
$cur_min = $intervals[$i][0];
$cur_max = $intervals[$i][1];
unset($intervals[$i]);
// find a random value within this interval
$r = rand($cur_min, $cur_max);
$result[] = $r;
// if there are valid intervals before and after $r,
// add these intervals back to the set of intervals
if ($r - $distance > $cur_min)
$intervals[] = array($cur_min, $r - $distance);
if ($r + $distance < $cur_max)
$intervals[] = array($r + $distance, $cur_max);
}
return $result;
}
答案 1 :(得分:1)
当你生成第n个数字时,在范围内生成它(min,min + range-2 * diff *(n-1)),然后迭代前面的数字,如果当前生成的数字是&#34 ;封端的&#34;按前一个数字,添加2 * diff。这是执行该操作的代码,但也考虑了先前生成的数字接近边界的情况(在这种情况下,您不需要将2 * diff添加到新生成的数字,只需要较小的数量):
define('min', 3000);
define('range', 6000);
define('diff', 200);
$numbers = array();
$bounds = array();
for($i = 0; $i<4; $i++){
$min = min;
$range = range;
foreach($bounds as $amount){
$range -= $amount;
}
$rnd = rand($min, $min + $range);
foreach($bounds as $position => $amount){
if($position <= $rnd){
$rnd += $amount;
}
else{
break;
}
}
$numbers[$i] = $rnd;
if($rnd <= min + diff){
$bounds['0'] = $rnd - min + diff;
}
elseif($rnd >= min + range - diff){
$bounds[strval($rnd-diff)] = min + range - $rnd + diff;
}
else{
$bounds[strval($rnd-diff)] = 2 * diff;
}
ksort($bounds);
}
print_r($numbers);
它没有优化,它运行在O(n ^ 2log(n)),甚至认为O(nlog(n))是可能的。