12

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

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

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

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

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

有任何想法吗?

4

10 回答 10

36

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

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

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

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

    return $result;
}

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

于 2012-10-31T23:55:29.753 回答
9

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

rand(1000,9999);
于 2020-02-26T16:15:09.420 回答
8

简短而甜蜜:

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

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

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

于 2012-10-31T23:57:25.357 回答
6

这是我正在使用的:

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。

于 2015-09-10T06:13:32.743 回答
2
function randomNDigitNumber($digits)
{
  $returnString = mt_rand(1, 9);
  while (strlen($returnString) < $digits) {
    $returnString .= mt_rand(0, 9);
  }
  return $returnString;
}

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

于 2017-01-06T20:20:15.560 回答
1
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} 将是您的范围。

于 2012-10-31T23:59:41.710 回答
1

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

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;
}
于 2014-10-02T00:48:03.127 回答
0

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

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);

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

于 2012-10-31T23:57:01.693 回答
0

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

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 次,因为$len1 并且只有 9 种唯一可能性(不包括 0),因此您需要了解需要多少随机数或选择足够大的随机数,$len而不用担心它.

于 2018-06-13T01:53:57.707 回答
0

如果环境是本地的,则无需生成随机数,并且 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;
    }
于 2021-02-27T10:27:39.343 回答