【问题标题】:PHP random number generation with conditionPHP随机数生成与条件
【发布时间】:2013-01-09 11:01:25
【问题描述】:

我最近接到了一项任务,但我失败了。我通常不问逻辑,但今天我不得不问。这是任务。

我不允许使用 php 的 rand() 函数。相反,我可以使用此功能。

function getRandom()
{
     return rand(1,5);
}

好的,我试过这个函数,但它的返回值一定是从 3 到 7。

function getMoreRandom()
{
    $value = getRandom();
    return $value + 2;

}

现在我必须定义一个 php 函数,它可以返回范围为 1 到 7 的随机数。我该怎么做?

【问题讨论】:

  • 这是家庭作业还是什么? getRandom 函数可以不改成只使用rand(1, 7) 吗?
  • 奇怪的任务,但也许你需要这样的东西:$value = getRandom(); $shouldAdd = getRandom(); if($shouldAdd >= 3) { return $value + 2; } else { return $value; }
  • @FAngel:确实是奇怪的任务。但是您的解决方案也很奇怪。而且它不是均匀分布的,它会比 1、2、6 和 7 更频繁地返回 3 到 5 之间的值。
  • 你应该看看这个:stackoverflow.com/questions/137783/…
  • 这不是一个家庭作业最近我接受了一次采访,他们通过问这个问题来测试我的逻辑

标签: php random numbers


【解决方案1】:

只是为了提出一个很好的问题,我认为这可能更通用。这意味着我们可能不想要基于 rand(1,5) 的 1-7,而是 3-7 或 1-10 等。

该函数适用于数字 1-25,因为我正在使用另一种二维数组的解决方案。

function getMoreRand($start, $end){
        $restart = $start; //Save $start value, to restart if we reach the $end number 
        $parser = 0; //Count number elements in 2d array
        $result = 0; //Return the result based on rand(1,5)

        //Create a 2d array(), 5x5 to simulate the 1-5 random number selection from rand(1,5)
        for($row = 0; $row < 5; $row++){
            for($col = 0; $col < 5; $col++){
                $vars[$row][$col] = $start;

                //If the array elements left <= selected range left
                if((25-$parser) <= ($end-$start)){
                    $vars[$row][$col] = 0;
                }else{
                    if($start == $end){
                        $start = $restart;
                    }else{
                        $start++;
                    }
                }       
                $parser++;

            }//END OF FOR COL LOOP
        }//END OF FOR ROW LOOP


        while($result == 0){
            $i = getRandom(); //Choose 1-5
            $j = getRandom(); //Choose 1-5
            $result = $vars[$i-1][$j-1]; //Get number from 2d array, based on rand(1,5)
        }

        echo $result;
    }

【讨论】:

    【解决方案2】:

    这不会是一个均匀分布(而且你没有指定它需要是)。

    对于最简单的解决方案,您不需要进行缩放或循环,您可以将随机 1 到 5,然后添加随机 0 到 2;

    function getMoreRandom()
    {
        return getRandom() + getRandom() % 3;
    }
    

    快速测试看看分布是什么样的:

    $results = array_fill(1, 7, 0);
    
    for ($i = 0; $i < 1000000; $i++) {
        $results[rand(1,5) + rand(1,5) % 3]++;
    }
    
    var_dump($results);
    

    如上所述,并非设计为均匀随机。

    array(7) {
      [1]=>
      int(39550) // 4%
      [2]=>
      int(120277) // 12%
      [3]=>
      int(200098) // 20%
      [4]=>
      int(199700) // 20%
      [5]=>
      int(200195) // 20% 
      [6]=>
      int(160200) // 16%
      [7]=>
      int(79980) // 8%
    }
    

    稍微复杂一点,和@flovs 不同的方法(我不喜欢他的循环可能永远持续 - 嘿,这就是随机性)

    function getMoreRandom()
    {
        for (
            $i = 0, $v = 0;
            $i < 7;
            $i++, $v += getRandom()
        );
    
        return $v % 7 + 1;
    }
    

    这会产生均匀分布

    array(7) {
      [1]=>
      int(14397)
      [2]=>
      int(14218)
      [3]=>
      int(14425)
      [4]=>
      int(14116)
      [5]=>
      int(14387)
      [6]=>
      int(14256)
      [7]=>
      int(14201)
    }
    

    【讨论】:

      【解决方案3】:
      function getMoreRandom()
      {
          $value = 0;
          for($i=1;$i<=5;$i++) $value += getRandom();
          return ($value % 7) + 1;
      }
      
      • 首先,调用getRandom 5 次,得到 5 到 25 的范围。这正好有 21 个值 - 7 的倍数。
      • 然后,求 7 的模数。这会产生一个介于 0 和 6 之间的数字,每个数字都有 21 分之 3 或 7 分之 1 的出现机会。
      • 然后,为正确的范围加一。

      【讨论】:

      • 这会将[1, 2, 3, 4, 5] 映射到[1, 2, 4, 5, 7]。你永远不会得到 3 或 6。
      • 这是真的,但鉴于您的种子只有五个可用值,并且您无法引入新的随机数,因此您几乎没有其他选择。
      • 没有地方说他不能多次使用 getRandom()。
      • 现在你得到了所有的数字,但不是均匀分布的。考虑掷两个骰子:掷 7 比掷 2 或 12 的可能性更大
      • 好的,如果两个骰子都不起作用,让我们试试 5(我知道这个问题已经回答,但我的回答是错误的,这让我很烦恼)。
      【解决方案4】:

      flov 的回答是正确的:

      function getMoreRandom()
      {
          do {
              $temp = 5 * (getRandom() - 1) + getRandom();
          } while ($temp > 21);
      
          return $temp % 7 + 1;
      }
      

      测试它:

      $aryResults = array_pad(array(),8,0);
      foreach(range(0,100000) as $i) $aryResults[getMoreRandom()]++;
      $intSum = array_sum($aryResults);
      foreach($aryResults as $intValue => $intCount) printf("Value %d Count %d (%.2f)\n",$intValue,$intCount,$intCount/$intSum);
      

      产生矩形分布

      Value 0 Count 0 (0,00)
      Value 1 Count 14328 (0,14)
      Value 2 Count 14316 (0,14)
      Value 3 Count 14185 (0,14)
      Value 4 Count 14197 (0,14)
      Value 5 Count 14322 (0,14)
      Value 6 Count 14361 (0,14)
      Value 7 Count 14292 (0,14)
      

      对不起,我没有对答案发表评论。显然我不能,因为我缺乏声誉(我是新来的)。

      【讨论】:

        【解决方案5】:

        我的解决方案:

        <?php
        
        function getRandom()
        {
             return rand(1,5);
        }
        
        $random_number = getRandom();
        $random_number += time();
        
        $random_number = ($random_number % 7) + 1;
        

        【讨论】:

        • 这行得通,但它使用了一个不允许的“外部”功能
        【解决方案6】:
        function getMoreRandom()
        {
            do {
                $temp = 5 * (getRandom() - 1) + getRandom();
            } while ($temp > 21);
        
            return $temp % 7 + 1;
        }
        

        【讨论】:

        • 我在测试后接受了它,这是我认为需要的。谢谢@flov
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2019-04-25
        • 2012-04-20
        • 1970-01-01
        • 1970-01-01
        • 2014-06-30
        • 1970-01-01
        • 2014-05-18
        相关资源
        最近更新 更多