得到4个随机数

时间:2014-05-11 12:14:42

标签: php algorithm random

我需要生成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);

有没有办法优化这个算法?

2 个答案:

答案 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))是可能的。