从破碎的数字范围中获取随机数

问题描述 投票:0回答:3

我想从间隔 1,49 中抽取一个随机数,但我想添加一个数字作为例外(比方说 44 ),我不能使用 round(rand(1,49)) 。所以我决定49 个数字 (1-49) 的数组,

unset($aray[44])
并应用
array_rand()

现在我想从区间 [$left,49] 中绘制一个数字,如何使用我之前使用的相同数组来做到这一点?该数组现在缺少值 44。

php arrays random
3个回答
3
投票

函数 pick 接受一个数组作为参数,其中包含您已经选择的所有数字。 然后,它将在该数组中的开始和结束之间选择一个 IS NOT 的数字。 它将将此数字添加到该数组中并返回该数字。

function pick(&$picked, $start, $end) {

    sort($picked);

    if($start > $end - count($picked)) {
        return false;
    }

    $pick = rand($start, $end - count($picked));
    foreach($picked as $p) {
        if($pick >= $p) {
            $pick += 1;
        } else {
            break;
        }
    }

    $picked[] = $pick;

    return $pick;
}

此函数将有效地获取不在数组中的随机数并且永远不会无限递归!

如您所愿地使用它:

$array = array(44); // you have picked 44 for example
$num = pick($array, 1, 49); // get a random number between 1 and 49 that is not in $array  

// $num will be a number between 1 and 49 that is not in $arrays

功能如何运作


假设您得到一个 1 到 10 之间的数字。并且您选择了两个数字(例如 2 和 6)。 这将使用 rand 选择 1 到(10 减 2)之间的数字:

rand(1, 8)

然后它会遍历每个被选中的数字并检查该数字是否更大。

例如:

If rand(1, 8) returns 2. 
  It looks at 2 (it is >= then 2 so it increments and becomes 3)
  It looks at 6 (it is not >= then 6 so it exits the loop)
  The result is: 3

If rand(1, 8) returns 3
  It looks at 2 (it is >= then 2 so it increments and becomes 4)
  It looks at 6 (it is not >= then 6 so it exits the loop)
  The result is 4

If rand(1, 8) returns 6
  It looks at 2 (it is >= then 2 so it increments and becomes 7)
  It looks at 6 (it is >= then 6 so it increments and becomes 8)
  The result is: 8

If rand(1, 8) returns 8
  It looks at 2 (it is >= then 2 so it increments and becomes 9)
  It looks at 6 (it is >= then 6 so it increments and becomes 10)
  The result is: 10

因此返回 1 到 10 之间的随机数,不会是 2 或 6。

我很早之前就实现了这个,将地雷随机放置在二维数组中(因为我想要随机地雷,但又想保证场上的地雷数量为一定数量)


0
投票

为什么不直接检查你的例外情况:

function getRand($min, $max) {
    $exceptions = array(44, 23);
    do {
        $rand = mt_rand($min, $max);
    } while (in_array($rand, $exceptions));
    return $rand;
}

请注意,如果您提供强制

mt_rand
返回异常字符的最小值和最大值,这可能会导致无限循环。 因此,如果你调用
getRand(44,44);
,虽然毫无意义,但会导致无限循环...(并且你可以通过函数中的一点逻辑来避免无限循环(检查函数中至少有一个非异常值)范围
$min
$max
)...

另一种选择是使用循环构建数组:

function getRand($min, $max) {
    $actualMin = min($min, $max);
    $actualMax = max($min, $max);
    $values = array();
    $exceptions = array(44, 23);
    for ($i = $actualMin; $i <= $actualMax; $i++) {
        if (in_array($i, $exceptions)) {
            continue;
        }
        $values[] = $i;
    }
    return $values[array_rand($values)];
}

0
投票

因为

unset()
array_rand()
都“使用”数组键,所以构建一个范围数组并翻转它是非常有意义的。 删除黑名单中的密钥,然后随机访问随机密钥。 演示

$array = array_flip(range(1, 49));
unset($array[44]);
echo array_rand($array);
© www.soinside.com 2019 - 2024. All rights reserved.