【问题标题】:PHP Generate x amount of random odd numbers within a rangePHP在一个范围内生成x个随机奇数
【发布时间】:2013-06-16 23:09:58
【问题描述】:

我需要在给定范围内生成 x 个随机奇数。 我知道这可以通过简单的循环来实现,但我不确定哪种方法是最好的,是否有更好的数学方法来解决这个问题。

编辑:我也不能多次使用相同的号码。

【问题讨论】:

    标签: php random numbers


    【解决方案1】:

    在一半范围内生成 x 个整数值,每个值加倍并加 1。

    回答修改后的问题:1) 生成范围内的候选者列表,将它们打乱,然后取第一个 x。或者 2) 根据我最初的建议生成值,如果生成的值在已生成值的列表中,则拒绝并重试。

    如果 x 是范围的很大一部分,第一个会更好,如果 x 相对于范围很小,则后者会更好。

    附录:早该想到这种方法,它基于条件概率。我不知道php(我是从“随机”标签来的),所以我将其表示为伪代码:

    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 是要生成的所需值的数量,upper_limit 是该范围内的最大奇数,rand 生成一个介于 0 和 1 之间的均匀分布的随机数。基本上,它会逐步遍历候选奇数集,并根据您还需要多少值以及还剩下多少候选值来接受或拒绝每个奇数。

    我已经对此进行了测试,它确实有效。与改组相比,它需要更少的中间存储,并且比最初的接受/拒绝需要更少的迭代。

    【讨论】:

    • 这可能会导致数字超出范围。例如。如果我的范围是 50,我会得到 25, 25*2+1 = 51
    • @carazh 我假设范围将根据允许的奇数指定。无论如何,现在问题已经修改,我的回答并不适用。
    • 好的,也谢谢!另一个答案中也有类似的方法。非常感谢,你们俩!
    • 最后一句很重要。如果 x 接近该范围,这可能会严重恶化。
    • @CaptainGiraffe 是的,我绝对建议在案例 2 中为已生成的集合使用哈希,因此至少每次尝试都可以在恒定时间内完成重复检查。
    【解决方案2】:

    生成范围内的元素列表,在随机系列中删除您想要的元素。重复 x 次。

    或者你可以生成一个范围内奇数的数组,然后进行随机播放

    生成很容易:

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

    随机播放

    shuffle( $range_array );
    

    拼接出第 x 个元素。

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

    这是一个完整的解决方案。

    【讨论】:

    • 已编辑,因为答案也已被编辑。这是开始,谢谢!
    • 要找到唯一的随机值,这是最复杂的。
    【解决方案3】:
    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));
    

    代码未经测试。刚写的。可以改进一点,但取决于你。

    【讨论】:

      【解决方案4】:

      此代码在区间 [1, 20] 中生成 5 个奇数唯一数。根据需要更改 $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);
      

      【讨论】:

        猜你喜欢
        • 2018-04-08
        • 1970-01-01
        • 2011-08-02
        • 1970-01-01
        • 1970-01-01
        • 2021-04-05
        • 2013-12-20
        • 2014-05-15
        • 2019-10-30
        相关资源
        最近更新 更多