简体   繁体   English

PHP生成一个范围内的x个随机奇数

[英]PHP Generate x amount of random odd numbers within a range

I need to generate x amount of random odd numbers, within a given range. 我需要在给定范围内生成x数量的随机奇数。 I know this can be achieved with simple looping, but I'm unsure which approach would be the best, and is there a better mathematical way of solving this. 我知道这可以通过简单的循环来实现,但是我不确定哪种方法是最好的,并且有更好的数学方法来解决这个问题。

EDIT: Also I cannot have the same number more than once. 编辑:另外,我不能多次拥有相同的号码。

Generate x integer values over half the range, and for each value double it and add 1. 生成超出范围一半的x个整数值,对于每个值将其加倍并加1。

ANSWERING REVISED QUESTION: 1) Generate a list of candidates in range, shuffle them, and then take the first x. 回答修订的问题:1)生成范围内的候选列表,将其洗牌,然后取第一个x。 Or 2) generate values as per my original recommendation, and reject and retry if the generated value is in the list of already generated values. 或者2)按照我的原始建议生成值,如果生成的值在已经生成的值列表中,则拒绝并重试。

The first will work better if x is a substantial fraction of the range, the latter if x is small relative to the range. 如果x是该范围的很大一部分,则第一个效果更好;如果x相对于该范围较小,则后者效果更好。

ADDENDUM: Should have thought of this approach earlier, it's based on conditional probability. 附录:应该早些考虑这种方法,它基于条件概率。 I don't know php (I came at this from the "random" tag), so I'll express it as pseudo-code: 我不了解php(我来自“ random”标记),因此我将其表示为伪代码:

generate(x, upper_limit)
  loop with index i from upper_limit downto 1 by 2
    p_value = x / floor((i + 1) / 2)
    if rand <= p_value
      include i in selected set
      decrement x
      return/exit if x <= 0
    end if
  end loop
end generate

x is the desired number of values to generate, upper_limit is the largest odd number in the range, and rand generates a uniformly distributed random number between zero and one. x是要生成的值的期望数量, upper_limit是该范围内的最大奇数,并且rand生成介于0和1之间的均匀分布的随机数。 Basically, it steps through the candidate set of odd numbers and accepts or rejects each one based how many values you still need and how many candidates still remain. 基本上,它会遍历候选集的奇数,并根据您仍然需要多少个值以及仍然剩余多少个候选者来接受或拒绝每个奇数。

I've tested this and it really works. 我已经测试过了,它确实有效。 It requires less intermediate storage than shuffling and fewer iterations than the original acceptance/rejection. 与改组相比,它所需的中间存储空间更少,与原始接受/拒绝相比,所需的迭代次数也更少。

Generate a list of elements in the range, remove the element you want in your random series. 生成范围内的元素列表,从随机序列中删除所需的元素。 Repeat x times. 重复x次。

Or you can generate an array with the odd numbers in the range, then do a shuffle 或者您可以生成一个奇数在范围内的数组,然后随机播放

Generation is easy: 生成很容易:

$range_array = array();
for( $i = 0; $i < $max_value; $i++){
    $range_array[] .= $i*2 + 1;
}

Shuffle 随机播放

shuffle( $range_array );

splice out the x first elements. 拼接出x个第一个元素。

$result = array_slice( $range_array, 0, $x );

This is a complete solution. 这是一个完整的解决方案。

function mt_rands($min_rand, $max_rand, $num_rand){
    if(!is_integer($min_rand) or !is_integer($max_rand)){
        return false;
    }
    if($min_rand >= $max_rand){
        return false;
    }
    if(!is_integer($num_rand) or ($num_rand < 1)){
        return false;
    }
    if($num_rand <= ($max_rand - $min_rand)){
        return false;
    }
    $rands = array();
    while(count($rands) < $num_rand){
        $loops = 0;
        do{
            ++$loops; // loop limiter, use it if you want to
            $rand = mt_rand($min_rand, $max_rand);
        }while(in_array($rand, $rands, true));
        $rands[] = $rand;
    }
    return $rands;
}

// let's see how it went
var_export($rands = mt_rands(0, 50, 5));

Code is not tested. 代码未经测试。 Just wrote it. 刚写。 Can be improved a bit but it's up to you. 可以改进一点,但要取决于您。

This code generates 5 odd unique numbers in the interval [1, 20]. 此代码在间隔[1,20]中生成5个奇数唯一数字。 Change $min, $max and $n = 5 according to your needs. 根据需要更改$ min,$ max和$ n = 5。

<?php
function odd_filter($x)
{
    if (($x % 2) == 1)
    {
        return true;

    }

    return false;
}

// seed with microseconds
function make_seed()
{
    list($usec, $sec) = explode(' ', microtime());
    return (float) $sec + ((float) $usec * 100000);
}
srand(make_seed());

$min = 1;
$max = 20;
//number of random numbers
$n = 5;

if (($max - $min + 1)/2 < $n)
{
    print "iterval [$min, $max] is too short to generate $n odd numbers!\n";
    exit(1);
}

$result = array();
for ($i = 0; $i < $n; ++$i)
{
    $x = rand($min, $max);

    //not exists in the hash and is odd
    if(!isset($result{$x}) && odd_filter($x))
    {
        $result[$x] = 1;
    }
    else//new iteration needed
    {
        --$i;
    }
}

$result = array_keys($result);
var_dump($result);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM