【问题标题】:Generate a random number with pre-defined length PHP生成具有预定义长度 PHP 的随机数
【发布时间】:2012-10-21 13:33:55
【问题描述】:

我正在尝试使用 mt_rand() 创建一个函数以生成真正的随机数,因为 rand() 还不够。

问题是我需要预先定义数字的长度,比如说我需要一个 10 位的随机数。

无论如何,我一直在胡闹,这就是我想出的:

    function randomNumber($length) {
        $min = str_repeat(0, $length-1) . 1;
        $max = str_repeat(9, $length);
        return mt_rand($min, $max);   
    }

理论上应该可行(据我所知),但事实并非如此。长度是完全随机的,也会抛出负值。

有什么想法吗?

【问题讨论】:

  • "为了生成一个真正的随机数" 好吧,你仍然会得到一个伪随机数。即使是 Mersenne twister 也无法为您提供真正的随机数。您可能会得到最接近的来自 random.org 的大气噪声数据。
  • 不管怎样,这不是问题,mt_rand() 比 rand() 随机得多。
  • rand(min,max) 将返回一个整数,因此仅在 32 位系统上的 PHP 32 位整数范围内......还要记住 0000000001 == 1,所以你的范围是 1 到 9999999999,你想要 $min = 1 。 str_repeat(0, $length-1)
  • 另外,对于 random.org,我不想每次都卷曲他们的网站。
  • @Karl.... 我再重复一遍:“rand(min,max) 将返回一个整数,因此仅在 32 位系统上的 PHP 32 位整数范围内”

标签: php random numbers


【解决方案1】:

除非您拥有其中一种量子静态的东西,否则您无法获得真正的随机数。但是,在基于 Unix 的操作系统上,/dev/urandom 可以实现“更多随机性”,如果你真的需要的话。

无论如何,如果你想要一个 n 位数字,这正是你应该得到的:n 个单独的数字。

function randomNumber($length) {
    $result = '';

    for($i = 0; $i < $length; $i++) {
        $result .= mt_rand(0, 9);
    }

    return $result;
}

您现有代码不起作用的原因是因为0000...01 仍然是1mt_rand,而且mt_rand 的范围不是无限的。负数是整数溢出。

【讨论】:

  • 有效点,但是,我刚刚尝试过,由于某种原因它仍然没有坚持长度,它生成了一个 12 位长的字符串。
  • @Karl:是的,对不起,我犯了一个错误。 mt_rand 包含在内。只需将10 更改为9
  • 如果第一个(和第二个,第三个...)是/是0,这仍然可以生成小于十位数的数字。
  • 顺便说一句 - 我可以得到一个没有量子静态事物的随机数 - 我只需要观察自然并量化它 - 我们都处于量子变化的状态 - 例如,我可以捕获放射性用数码相机和一块 Americanum(来自烟雾探测器)很容易腐烂。随机性并不难,它只是在机器内部很难。
  • @MyWetSocks:没有前导零,对于可以传递长度的通用函数,它 (a) 不会节省太多,并且 (b) 不适用于 10 位或更多位(secure.php.net/manual/en/function.mt-getrandmax.php)。
【解决方案2】:

又短又甜:

我假设只有合法的数字,而不是像 00010 这样的字符串。尝试使用您的数字大小为:

  $min = pow(10, $length - 1) ;
  $max = pow(10, $length) - 1;
  return mt_rand($min, $max);   

唯一不起作用的是当长度为 1 时,单个数字“0”将不是可能返回的值。

【讨论】:

  • 我想你可能打算做“长度的十次方”,而不是“长度乘以十”。
  • @minitech 是的,我在完成编辑并在 codepad.org 中运行之前点击了提交
  • mt_rand() 不支持任意长度的随机数。
  • @Sven 你的意思是提供的解决方案在某些情况下不起作用吗?我认为它会起作用,因为 $min 和 $max 变量将分别包含长度 $length 的最小和最大数。因此,函数 mt_rand() 将只有一个长度作为其输出的选项。
  • mt_rand() 不输出任意数字。无论您提供什么最小值和最大值,它都被限制为不创建大于mt_getrandmax() 的整数。这使得这个答案对于您可以提供的大多数 $length 值都失败了,除了介于 1 和大约 7 或 8 之间的值。请参阅我对问题本身的评论:stackoverflow.com/questions/13169025/…
【解决方案3】:

只需将范围指定为 rand 方法,如果您需要 4 位随机数,则将其用作

rand(1000,9999);

【讨论】:

    【解决方案4】:

    这是我正在使用的:

    function random_number($length)
    {
        return join('', array_map(function($value) { return $value == 1 ? mt_rand(1, 9) : mt_rand(0, 9); }, range(1, $length)));
    }
    

    一行,漂亮又简单!该数字永远不会以 0 开头,并且允许在任何其他位置为 0。

    【讨论】:

      【解决方案5】:
      function randomNDigitNumber($digits)
      {
        $returnString = mt_rand(1, 9);
        while (strlen($returnString) < $digits) {
          $returnString .= mt_rand(0, 9);
        }
        return $returnString;
      }
      

      第一行确保任何数字前面都没有“0”,例如012、0598...等值将被丢弃,其余的很容易

      【讨论】:

        【解决方案6】:
        function randomNumber($length) {
            $min = 1 . str_repeat(0, $length-1);
            $max = str_repeat(9, $length);
            return mt_rand($min, $max);   
        }
        

        您的 concat 1 位于错误的位置,您的范围是 $length=2:{01,99} - 有时是 01-09,表示为 1-9 而不是 01-09。从 10 开始:{10,99} 将是您的范围。

        【讨论】:

        • PHP 致命错误:未捕获类型错误:mt_rand():参数 #1 ($min) 必须是 int 类型,字符串在 /workspace/Main.php:7 中给出 堆栈跟踪:#0 /workspace /Main.php(7): mt_rand() #1 /workspace/Main.php(10): randomNumber() #2 {main} 在第 7 行的 /workspace/Main.php 中抛出
        【解决方案7】:

        将其用于包含字母和数字的特定长度的字符串。经过测试。

        protected function randomToken($length = 4, $result='') {
        
            for($i = 0; $i < $length; $i++) {
        
                $case = mt_rand(0, 1);
                switch($case){
        
                    case 0:
                        $data = mt_rand(0, 9);
                        break;
                    case 1:
                        $alpha = range('a','z');
                        $item = mt_rand(0, 25);
        
                        $data = strtoupper($alpha[$item]);
                        break;
                }
        
                $result .= $data;
            }
        
            return $result;
        }
        

        【讨论】:

        • 我认为您可以改用以下代码:return substr(uniqid(), 0, $length);
        【解决方案8】:

        您不应该从限制随机数的长度开始。而是积累足够长的输出,然后将其切割到正确的长度:

        while (strlen($value) < $length) {
            $value .= str_pad(mt_rand(00000, 99999), 5, "0", STR_PAD_LEFT);
        }
        // as pairs of five were added before, eventually remove some again
        return substr($value, 0, $length);
        

        填充应该在那里,因为即使是零也是随机生成的,应该保留。

        【讨论】:

        • 如果你的随机数生成器不好,这可能会有问题,因为你正在减少你的世界并且数字可以在组中重复 - 这一切都取决于实施。 (首先可以说发电机也是如此)。但我会避免这种情况。
        • mt_rand() 接受两个整数值。零写成“0”还是“00000”真的没关系,但后者是八进制数格式!
        【解决方案9】:

        假设您使用的范围很小,并且不想两次生成相同的数字,那么如何:

        function random(int $len): int
        {
            static $track = [];
            
            $min = 1 . str_repeat(0, $len - 1);
            $max = str_repeat(9, $len);
            $num = mt_rand($min, $max);
            
            // if was generated before, try again
            if (in_array($num, $track))
            {
                return random($len);
            }
            
            // store and return
            return $track[] = $num;
        }
        

        通过仅启动一次的静态变量跟踪生成的随机数,将防止生成相同的数字两次,但请注意,如果您超过 $len 规定的唯一可能性的数量,您将陷入无限环形。例如,您不能调用 random(1) 超过 9 次,因为 $len 是 1,并且只有 9 个唯一的可能性(不包括 0)所以您需要了解您需要多少随机数或选择大够了$len,不用担心。

        【讨论】:

          【解决方案10】:

          如果环境是本地的,则无需生成随机数,mt_rand 与 rand 类似,但速度快四倍

              protected function generateRandomNumber(int $length = 6)
              {
                  $rand = '';
                  $env = env('APP_ENV');
                  for ($i = 1; $i <= $length; $i++) {
                      $rand .= ($env == 'local') ? $i : mt_rand(($i == 1) ? 1 : 0, 9);
                  }
          
                  return (int) $rand;
              }
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2015-05-11
            • 1970-01-01
            • 2020-03-11
            • 2017-07-02
            • 1970-01-01
            相关资源
            最近更新 更多