In PHP, how do I generate a big pseudo-random number?

前端 未结 14 1143
遇见更好的自我
遇见更好的自我 2020-12-03 14:12

I\'m looking for a way to generate a big random number with PHP, something like:

mt_rand($lower, $upper);

The closer I\'ve

相关标签:
14条回答
  • 2020-12-03 14:52

    Here is pseudocode:

    
    // generate a random number between N1 and N2
    
    rangesize = N2 - N1 + 1
    randlen = length(rangesize) + 4 // the 4 is to get more digits to reduce bias
    temp = BigRandomNumber(randlen) // generate random number, "randlen" digits long
    temp = temp mod rangesize
    output N1 + temp
    
    

    Notes:

    • all arithmetic here (except in the second line) must be arbitrary precision: use the bcmath library for this
    • in the second line, "length" is number of digits, so the "length" of 1025 would be 4
    0 讨论(0)
  • 2020-12-03 14:55

    This may work:

    • Split the number into an array with 9 numbers or less ("the rest") ... 9 chars because max rand number is 2147483647 on my machine.
    • For each "9-or-less numbers array block", create a random number.
    • Implode the array and you will now have a usable random number.

    Example code that illustrates the idea (notice: the code is undone)

    function BigRandomNumber($min,$max) {
    // Notice: Will only work when both numbers have same length.
    echo (strlen($min) !== strlen($max)) ? "Error: Min and Max numbers must have same length" : NULL;
    $min_arr = str_split($min);
    $max_arr = str_split($max);
    // TODO: This loop needs to operate on 9 chars ($i will increment by $i+9)
    for($i=0; $i<=count($max_arr); $i++) {
        if($i == 0) {
            // First number: >=first($min) and <=first($max).
            $new_arr[$i] = rand( $min_arr[0], $max_arr[0]);
        } else if($i == count($max_arr)) {
            // Last number <= $max .. not entirely correct, feel free to correct it.
            $new_arr[$i] = rand(0, substr($max,-1));
        } else {
            $new_arr[$i] = rand(0,9);
        }
    }
    return implode($new_arr);
    }
    
    0 讨论(0)
  • 2020-12-03 14:56

    Generating 'n' random chars is not really an option, as random('9999999999') could still, theoretically, return 1...

    Here's a quite simple function:

    function bcrand($max) { 
        return bcmul($max, (string)mt_rand() / mt_getrandmax() ); 
    }
    

    Note that it will NOT return N bits of randomness, just adjust scale

    0 讨论(0)
  • 2020-12-03 14:57

    This might work for you. (I am not sure why you need it, so it might not be the best way to do it, but it should fit your requirements):

    <?php
    function bigRandomNumber($min, $max)
    {
     // check input first
        if ($max < $min) { return false; }
        // Find max & min length of the number
        $lenMin = strlen ($min);
        $lenMax = strlen ($max);
    
        // Generate a random length for the random number
        $randLen = $lenMin + mt_rand(0, $lenMax - $lenMin);
        /* Generate the random number digit by digit, 
           comparing it with the min and max values */
     $b_inRange = false;
        for ($i = 0; $i < $randLen; $i++)
     {
      $randDigit = mt_rand(0,9);
    
      /* As soon as we are sure that the number will stay 
              in range, we can stop comparing it to min and max */
      if (!$b_inRange)
      {
       $tempRand = $rand . $randDigit;
       $tempMin = substr($min, 0, $i+1);
       $tempMax = substr($max, 0, $i+1);
       // Make sure that the temporary random number is in range
       if ($tempRand < $tempMin || $tempRand > $tempMax)
       {
        $lastDigitMin = substr($tempMin, -1);
        $lastDigitMax = substr($tempMax, -1);
        $tempRand = $rand . @mt_rand($lastDigitMin, $lastDigitMax);
       }
       /* Check if $tempRand is equal to the min or to the max value. 
                   If it is not equal, then we know it will stay in range */
       if ($tempRand > $tempMin && $tempRand < $tempMax)
       {
        $b_inRange = true;
       }
      }
      else
      {
       $tempRand = $rand . $randDigit;
      }
      $rand = $tempRand;  
     }
     return $rand;
    }
    

    I tried a couple times and it looks like it works OK. Optimize if needed. The idea is to start by figuring out a random length for your random number that would put it in the acceptable range. Then generate random digits one by one up to that length by concatenating. If it is not in range, generate a new random digit in range and concatenate.

    I use the fact that PHP will convert a string to a number to take advantage of the string functions. Of course this generates a warning for mt_rand, but as we use only numbers, it should be safe to suppress it.

    Now, I have to say that I am quite curious as to why you need this in the first place.

    0 讨论(0)
  • 2020-12-03 14:59
    /* Inputs: 
     * min - GMP number or string: lower bound
     * max - GMP number or string: upper bound
     * limiter - GMP number or string: how much randomness to use.
     *  this value is quite obscure (see `gmp_random`, but the default
     *  supplies several hundred bits of randomness, 
     *  which is probably enough.
     * Output: A random number between min (inclusive) and max (exclusive).
    */
    function BigRandomNumber($min, $max, $limiter = 20) {
      $range = gmp_sub($max, $min);
      $random = gmp_random();
      $random = gmp_mod($random, $range);
      $random = gmp_add($min, $random);
      return $random;
    }
    

    This is just the classic formula rand_range($min, $max) = $min + rand() % ($max - $min) translated to arbitrary-precision arithmetic. It can exhibit a certain amount of bias if $max - $min isn't a power of two, but if the number of bits of randomness is high enough compared to the size of $max - $min the bias becomes negligible.

    0 讨论(0)
  • 2020-12-03 15:00

    This will give you more zeros in your giant random number and you can also specify the length of the giant random number (can your giant random number start with a 0? if not, that can also be easily implemented)

    <?php
    
    $randNumberLength = 1000;  // length of your giant random number
    $randNumber = NULL;
    
    for ($i = 0; $i < $randNumberLength; $i++) {
        $randNumber .= rand(0, 9);  // add random number to growing giant random number
    
    }
    
    echo $randNumber;
    
    ?>
    

    Good luck!

    0 讨论(0)
提交回复
热议问题