• 首页
  • vue
  • TypeScript
  • JavaScript
  • scss
  • css3
  • html5
  • php
  • MySQL
  • redis
  • jQuery
  • mt_rand()

    (PHP 4, PHP 5, PHP 7)

    生成更好的随机数

    说明

    mt_rand(void): int
    mt_rand(int $min,int $max): int

    很多老的 libc 的随机数发生器具有一些不确定和未知的特性而且很慢。PHP 的rand()函数默认使用 libc 随机数发生器。mt_rand()函数是非正式用来替换它的。该函数用了» Mersenne Twister中已知的特性作为随机数发生器,它可以产生随机数值的平均速度比 libc 提供的 rand()快四倍。

    如果没有提供可选参数$min$maxmt_rand()返回 0 到mt_getrandmax()之间的伪随机数。例如想要 5 到 15(包括 5 和 15)之间的随机数,用mt_rand(5, 15)

    参数

    $min

    可选的、返回的最小值(默认:0)

    $max

    可选的、返回的最大值(默认:mt_getrandmax())

    返回值

    返回$min(或者 0)到$max(或者是到mt_getrandmax(),包含这个值)之间的随机整数。

    更新日志

    版本说明
    4.2.0随机数发生器自动进行播种。

    范例

    Example #1mt_rand()例子

    <?php
    echo mt_rand() . "\n";
    echo mt_rand() . "\n";
    echo mt_rand(5, 15);
    ?>
    

    以上例程的输出类似于:

    1604716014
    1478613278
    6
    

    注释

    Caution

    The distribution ofmt_rand()return values is biased towards even numbers on 64-bit builds of PHP when$maxis beyond2^32.

    参见

    i wanted to spot out the big difference between rand and mt_rand when producing images using randomness as noise.
    for example this is a comparation between rand and mt_rand on a 400x400 pixel png: http://oi43.tinypic.com/vwtppl.jpg
    code:
    <?php
    header("Content-type: image/png");
    $sizex=800;
    $sizey=400;
    $img = imagecreatetruecolor($sizex,$sizey);
    $ink = imagecolorallocate($img,255,255,255);
    for($i=0;$i<$sizex/2;$i++) {
     for($j=0;$j<$sizey;$j++) {
     imagesetpixel($img, rand(1,$sizex/2), rand(1,$sizey), $ink);
     }
    }
     
    for($i=$sizex/2;$i<$sizex;$i++) {
     for($j=0;$j<$sizey;$j++) {
     imagesetpixel($img, mt_rand($sizex/2,$sizex), mt_rand(1,$sizey), $ink);
     }
    }
    imagepng($img);
    imagedestroy($img);
    ?>
    the differences reduce when reducing the pixels of the image.. infact for a 100x100 pixel image the noise produced from the rand function is much more realistic than how it is for a 400x400 image: http://oi39.tinypic.com/5k0row.jpg
    (rand is on the left, mt_rand on the right)
    mt_rand is not calculated by Mersenne Twister.
    https://github.com/php/php-src/commit/a0724d30817600540946b41e40f4cfc2a0c30f80
    To quickly build a human-readable random string for a captcha per example :
    <?php
    function random($length = 8)
    {   
      $chars = 'bcdfghjklmnprstvwxzaeiou';
      
      for ($p = 0; $p < $length; $p++)
      {
        $result .= ($p%2) ? $chars[mt_rand(19, 23)] : $chars[mt_rand(0, 18)];
      }
      
      return $result;
    }
    ?>
    Note that I have removed q and y from $chars to avoid readability problems.
    The seed is the PID + LCG (https://github.com/php/php-src/search?q=GENERATE_SEED&unscoped_q=GENERATE_SEED)
    rand() comes from the libc, and mt_rand() is internal to PHP. So the differences vary with their respective versions.
    On a 64b Debian Stretch with PHP 5.6.21, there is no visible difference: http://oi64.tinypic.com/2nkqas6.jpg
    This image compares the two functions. In the top half with random points, in the lower half with random intensity on each point. This is totally different from what was obtained 4 years ago in another note, with an unknown environment.
    Here is the code for this visual comparison.
    <?php
    $sizex = 400;
    $sizey = 400;
    $img = imagecreatetruecolor(2 * $sizex, 2 * $sizey);
    $white = imagecolorallocate($img, 255, 255, 255);
    $inks = array_map(
      function($r) use($img) { return imagecolorallocate($img, $r, $r, $r); },
      range(0, 255)
    );
    for ($x = 0 ; $x < $sizex ; $x++) {
      for ($y = 0 ; $y < $sizey ; $y++) {
        // placing ($sizex x $sizey) white points at random in the top half
        imagesetpixel($img, rand(0, $sizex - 1), rand(0, $sizey - 1), $white);
        imagesetpixel($img, $sizex + mt_rand(0, $sizex - 1), mt_rand(0, $sizey - 1), $white);
        // random intensity for each point in the lower half
        imagesetpixel($img, $x, $sizey + $y, $inks[rand(0, 255)]);
        imagesetpixel($img, $sizex + $x, $sizey + $y, $inks[mt_rand(0, 255)]);
      }
    }
    header("Content-type: image/png");
    imagepng($img);
    ?>
    
    The algorithm used by mt_rand() changed in PHP 5.2.1. If you are relying on getting the same sequence from mt_rand() after calling mt_srand() with a known seed, upgrading to PHP 5.2.1 will break your code. See http://bugs.php.net/bug.php?id=40724 for something of an explanation; there is no workaround.
    If you need some pseudorandom bits for security or cryptographic purposes (e.g.g., random IV for block cipher, random salt for password hash) mt_rand() is a poor source. On most Unix/Linux and/or MS-Windows platforms you can get a better grade of pseudorandom bits from the OS or system library, like this:
    <?php
    // get 128 pseudorandom bits in a string of 16 bytes
    $pr_bits = '';
    // Unix/Linux platform?
    $fp = @fopen('/dev/urandom','rb');
    if ($fp !== FALSE) {
      $pr_bits .= @fread($fp,16);
      @fclose($fp);
    }
    // MS-Windows platform?
    if (@class_exists('COM')) {
      // http://msdn.microsoft.com/en-us/library/aa388176(VS.85).aspx
      try {
        $CAPI_Util = new COM('CAPICOM.Utilities.1');
        $pr_bits .= $CAPI_Util->GetRandom(16,0);
        // if we ask for binary data PHP munges it, so we
        // request base64 return value. We squeeze out the
        // redundancy and useless ==CRLF by hashing...
        if ($pr_bits) { $pr_bits = md5($pr_bits,TRUE); }
      } catch (Exception $ex) {
        // echo 'Exception: ' . $ex->getMessage();
      }
    }
    if (strlen($pr_bits) < 16) {
      // do something to warn system owner that
      // pseudorandom generator is missing
    }
    ?>
    NB: it is generally safe to leave both the attempt to read /dev/urandom and the attempt to access CAPICOM in your code, though each will fail silently on the other's platform. Leave them both there so your code will be more portable.
    Allows characters 0-9, a-z
    Weighted (and tested) ok.
    <?php
    function generate_string ($length = 20)
    {
      $nps = "";
      for($i=0;$i<$length;$i++)
      {
        $nps .= chr( (mt_rand(1, 36) <= 26) ? mt_rand(97, 122) : mt_rand(48, 57 ));
      }
      return $nps;
    }
    ?>
    
    a better (and likely faster) way to generate a random 6-digit hex string:
    <?php
    $num = mt_rand ( 0, 0xffffff ); // trust the library, love the library...
    $output = sprintf ( "%06x" , $num ); // muchas smoochas to you, PHP!
    return $output;
    ?>
    The mt_rand function won't give you a number outside the bounds you asked for -- no need to and-off the top bits -- and the sprintf function has params for length-padding & hexidecimal output. It's likely faster because most of the work is being done by the wicked fast C functions that PHP sits on top of, though YMMV in that dept.
    just another example: both of these routines return a random decimal number between -1 and 1... since rand() only returns a max 'integer' value while mt_rand() return a max 'long' value -- at least on some platforms -- mt_rand() could be the better precision choice for some on any variation to this routine (but i don't think it matters here):
    <?php
    echo "-1 to 1 rand() value: ". (rand(getrandmax()*-1,getrandmax())/getrandmax()). "\n<br/>";
    echo "-1 to 1 mt_rand() value: ". (mt_rand(mt_getrandmax()*-1,mt_getrandmax())/mt_getrandmax()). "\n";
    ?>
    
    Another graphical comparison of rand() and mt_rand(). It effectively draws a graph showing how the last generated number affects the next by plotting the numbers in consecutive pairs against each other.
    <?php
    header("Content-type: image/png");
    $sizex=800;
    $sizey=800;
    $img = imagecreatetruecolor(2 * $sizex,$sizey);
    $black = imagecolorallocate($img,0, 0, 0);
    imagefilledrectangle($img, 0, 0, 2 * $sizex, $sizey, imagecolorallocate($img, 255, 255, 255));
    $p = 0;
    for($i=0; $i < 100000; $i++) {
      $np = rand(0,$sizex);
      imagesetpixel($img, $p, $np, $black);
      $p = $np;
    }
    $p = 0;
    for($i=0; $i < 100000; $i++) {
      $np = mt_rand(0,$sizex);
      imagesetpixel($img, $p + $sizex, $np, $black);
      $p = $np;
    }
    imagepng($img);
    imagedestroy($img);
    ?>
    
    I wrote another function to get a random float, if its not precise enougth jut add some '0' to the $mul parameter.
    <?php
    function f_rand($min=0,$max=1,$mul=1000000){
      if ($min>$max) return false;
      return mt_rand($min*$mul,$max*$mul)/$mul;
    }
    ?>
    I made following tests:
    <?php
      echo f_rand()."<br>";       //0.497153
      echo f_rand(0.5)."<br>";      //0.857822
      echo f_rand(0.5,0.6)."<br>";    //0.599956
      echo f_rand(0,10)."<br>";     //5.801949
      echo f_rand(0,2,2)."<br>";     //1.5
      echo f_rand(0,2,10)."<br>";    //1.7
    ?>
    
    mt_rand() is not faster than rand() !
    Tested over 100'000 iterations, with none/various/random arguments, mt_rand is always 3% slower than rand().
    With PHP 5.3.3, we're seeing odd behavior on 32 bit Linux.
    This works fine on 64 bit Linux: 
    <?php
    printf ("%08x\n", mt_rand (0, 0xFFFFFFFF));
    ?>
    but on our 32 bit Linux development server, it's always yielding "00000000". 
    On that same machine, this: 
    <?php
    printf ("%08x\n", mt_rand (0, 0xFFFFFFF0));
    ?> 
    seems to always yield either 00000000 or a number in the range fffffff2 to ffffffff. This: 
    <?php
    printf ("%08x\n", mt_rand (0, 0xFFFFFF00));
    ?> 
    gives numbers where the last two digits vary, and so on through at least 0xF0000000. 
    However, this: 
    <?php
    printf ("%08x\n", mt_rand (0, 0x7FFFFFFF));
    ?>
    seems to be well-behaved.
    The moral? On 32 bit systems, be careful about crossing the signed number boundary, 0x7FFFFFFF.
    Another generic random string function, but very small and fast.
    <?php
    function mt_rand_str ($l, $c = 'abcdefghijklmnopqrstuvwxyz1234567890') {
      for ($s = '', $cl = strlen($c)-1, $i = 0; $i < $l; $s .= $c[mt_rand(0, $cl)], ++$i);
      return $s;
    }
    echo mt_rand_str(8); // Something like mp2tmpsw
    echo mt_rand_str(6, '0123456789ABCDEF'); // Something like B9CD0F
    ?>
    
    To reiterate the message about *not* using mt_rand() for anything security related, here's a new tool that has been just posted that recovers the seed value given a single mt_rand() output:
    http://www.openwall.com/php_mt_seed/README
    /dev/urandom provides high entropy, but it is important to remember that it is created by collecting random os garbage from memory - if not enough of that garbage is created reading the file will just block the whole process until there is enough entropy to generate the requested random bytes. in debian-based setups, the rng-tools package can be used to manage entropy.
    Another good way to get a random float is to divide the result of mt_rand.
    Let's say we want a float between 0.75 and 1.25.
    <?php
    $i = mt_rand(75,125) / 100;
    ?>
    
    Fast, pseudo-random binary data generation using mt_rand():
    <?php
    function rnd_bin( $length )
    {
      while( @$c++ * 16 < $length )
        @$tmp .= md5( mt_rand(), true );
      return substr( $tmp, 0, $length );
    }
    ?>
    
    If you need a predictable set of numbers for a given seed, you may use the following Pure-PHP implementation of a Mersenne Twister
    <?php
    class Mersenne_Twister
    {
     private $state = array ();
     private $index = 0;
     public function __construct($seed = null) {
      if ($seed === null)
       $seed = mt_rand();
      $this->setSeed($seed);
     }
     public function setSeed($seed) {
      $this->state[0] = $seed & 0xffffffff;
      for ($i = 1; $i < 624; $i++) {
       $this->state[$i] = (((0x6c078965 * ($this->state[$i - 1] ^ ($this->state[$i - 1] >> 30))) + $i)) & 0xffffffff;
      }
      $this->index = 0;
     }
     private function generateTwister() {
      for ($i = 0; $i < 624; $i++) {
       $y = (($this->state[$i] & 0x1) + ($this->state[$i] & 0x7fffffff)) & 0xffffffff;
       $this->state[$i] = ($this->state[($i + 397) % 624] ^ ($y >> 1)) & 0xffffffff;
       if (($y % 2) == 1) {
        $this->state[$i] = ($this->state[$i] ^ 0x9908b0df) & 0xffffffff;
       }
      }
     }
     public function getNext($min = null, $max = null) {
      if (($min === null && $max !== null) || ($min !== null && $max === null))
       throw new Exception('Invalid arguments');
      if ($this->index === 0) {
       $this->generateTwister();
      }
      $y = $this->state[$this->index];
      $y = ($y ^ ($y >> 11)) & 0xffffffff;
      $y = ($y ^ (($y << 7) & 0x9d2c5680)) & 0xffffffff;
      $y = ($y ^ (($y << 15) & 0xefc60000)) & 0xffffffff;
      $y = ($y ^ ($y >> 18)) & 0xffffffff;
      $this->index = ($this->index + 1) % 624;
      if ($min === null && $max === null)
       return $y;
      $range = abs($max - $min);
      return min($min, $max) + ($y % ($range + 1));
     }
    }
    ?>
    
    A class to generate 99.5% unqiue strings. I found that there is only one or two characters common between two subsequent strings.
    <?php
    class Local_RandomString {
     
     protected $_length;
     protected $_prevRand;
     public function __construct($length = 15) {
      
      $this->_length = $length;
     }
     public function getRand() {
      
      $randStr = null;  
      $args[] = 'N' . $this->_length;
      for($i = 0; $i < $this->_length; $i++) {
       $args[] = mt_rand();   
      }
      
      $randStr = substr(base64_encode((call_user_func_array('pack', $args))), 1, $this->_length);
      $this->_prevRand = $randStr;
      return $randStr;
     }
     public function setLength($l) {
      
      $this->_length = (int) $l;
      
      if($this->_length <= 0) {
       throw new Exception('Invalid random string length');
      }
     }
     public function getPrevRand() {
      
      return $this->_prevRand;
     }
    }
    ?>
    
    The following function generates a string of arbitrary length (with limitations), composed of random PHP characters (i.e. each an 8-bit value - a byte). Suitable for generating random session strings. Encode as Base64 to transmit over network, where required.
    ** The function is pretty much one of the fastest (if not THE fastest) methods of generating random strings, as opposed to numerous examples given on this page which go about with char-by-char generation. Sloppy benchmarks estimate a factor of 10 speedup. Keep your websites lean, people. **
    The only thing to keep in mind is that, by design, it outputs 8-bit characters, and thus the generated string is not automatically suitable for transmission with various network protocols, unless altered, f.e. URL- or Base64- encoded. Also, again by design, the length of the string is a multiple of 4 characters/bytes. The version below produces a 24 character long string. This will also give you a clean input to get a 32 character long Base64 encoded variant of it.
    <?php
    function gen_rand_str_24()
    {
       return pack('N6', mt_rand(), mt_rand(), mt_rand(),
         mt_rand(), mt_rand(), mt_rand());
    }
    ?>
    I leave it an exercise to the reader to write a generic (i.e. arbitrary double word length, not 6 dwords as in above) version of it.
    Just another random password generator. Assembles passwords such as these:
    N_v85kA2_s
    8k4jz94_H0
    30824n6VcN
    useful for... whatever. ;)
    $underscores holds the maximum allowed number of underscores. Default is two. The function is programmed to not add an underscore at the beginning or end of the password, right after another underscore, or if the maximum # has already been used.
    $length holds the length you want the password to be. Default is 10 characters long.
    <?php
    function alphanumericPass()
    {  
      // Do not modify anything below here
      $underscores = 2; // Maximum number of underscores allowed in password
      $length = 10; // Length of password
      
      $p ="";
      for ($i=0;$i<$length;$i++)
      {  
        $c = mt_rand(1,7);
        switch ($c)
        {
          case ($c<=2):
            // Add a number
            $p .= mt_rand(0,9);  
          break;
          case ($c<=4):
            // Add an uppercase letter
            $p .= chr(mt_rand(65,90));  
          break;
          case ($c<=6):
            // Add a lowercase letter
            $p .= chr(mt_rand(97,122));  
          break;
          case 7:
             $len = strlen($p);
            if ($underscores>0&&$len>0&&$len<($length-1)&&$p[$len-1]!="_")
            {
              $p .= "_";
              $underscores--;  
            }
            else
            {
              $i--;
              continue;
            }
          break;    
        }
      }
      return $p;
    }
    ?>
    
    Re: euxneks at NOSPAMgmail dot com
    You might also want to add STR_PAD_LEFT and have:
    <?php
    echo '#' . str_pad( base_convert( mt_rand(0, ( 255*255*255) ), 10, 16 ), 6, '0', STR_PAD_LEFT) . "\n";
    ?>
    
    Re: keith at ourwebsite dot ca
    Here's another way to do it, in one line :)
    <?php
    echo '#' . str_pad( base_convert( mt_rand(0, ( 255*255*255) ), 10, 16 ), 6, '0' ) . "\n";
    ?>
    str_pad is there in case mt_rand chooses a number that will generate a hex value with less than 6 characters. (you could leave that out but it's not a very clean way to write the hex colors is it :)
    Here is a example of a very small, compact, quite random-random string generator. It will make a string with uppercase & lowercase letters, with numbers. You simply need to set $len in the for() structure, and then the string will be in $r. It has been designed for size, while it's still quite fast. Mind the wrapping, it should be 1 line.
    <?php 
    for($len=8,$r='';strlen($r)<$len;$r.=chr(!mt_rand(0,2)?
    mt_rand(48,57):(!mt_rand(0,1)?mt_rand(65,90): mt_rand
    (97,122))));
    ?>
    Armond Carroll
    Below, andrei suggested a function for generating a list of unique integers, randomly arranged. In response to a note below that his solution is inefficient, I'm providing an O(N) solution which should be much more efficient, yet still yield a good guarantee of producing randomly ordered integers.
    <?php
    function SwapShuffle($min, $max) {
     $last = $max - $min;
     for ($i=0; $i<=$last; $i++) {
      $arr[$i] = $min + $i;
     }
     for ($run=0; $run<7; $run++) {
      for ($i=0; $i<=$last; $i++) {
       $target = mt_rand(0, $last);
       $swap = $arr[$target];
       $arr[$target] = $arr[$i];
       $arr[$i] = $swap;
      }
     }
     return $arr;
    }
    // Call as:
    $result = SwapShuffle(10, 30);
    foreach ($result as $num) {
     echo "$num\n";
    }
    ?>
    
    Do not rely on the strength of any 'home-brewed' cryptographic algorithm, such as the one posted by dmoree at coker dot edu. Algorithms such as MD5 and SHA-1 have been the subject of intense academic research and have known security properties.
    While it is true that MD5 and SHA-1 are generally no longer recommended for use in new cryptosystems, there are newer algorithms such as SHA-256 that address the older algorithms' weaknesses. These newer algorithms have not received quite as much scrutiny as their older counterparts, but have still been studied much more carefully than your home-brewed algorithm, most likely.
    Dmoree at coker dot edu's concern about rainbow tables is best addressed by a properly applied salting technique. Every bit of 'salt' added to a cryptographic hash effectively extends the complexity of the password and thus the size of the rainbow table needed to crack it.
    Furthermore, wisely chosen password strength policies can mitigate such attacks.
    performance: for a repetitive task, it's much faster not to use the limit parameters, as shown below. just use the % operator.
    $t=microtime(true);
    for($i=0;$i<1000000;$i++)
     mt_rand()%3;
    echo microtime(true)-$t;
    echo '|';
    $t=microtime(true);
    for($i=0;$i<1000000;$i++)
     mt_rand(0,2);
    echo microtime(true)-$t;
    echo '|';
    $t=microtime(true);
    for($i=0;$i<1000000;$i++)
     mt_rand();
    echo microtime(true)-$t;
    output: 0.316797971725|0.442242145538|0.253082036972
    mt_rand function returns just a whole numbers. If you want a random float, then here's an elegant way:
    <?php
    function random_float ($min,$max) {
      return ($min+lcg_value()*(abs($max-$min)));
    }
    ?>
    
    Here is my Function to generate an Array with unique random Numbers between "$from" and "$to".
    <?php
    function random_number_array($count, $from, $to){
      for($i=$from;$i<$to;$i++){
      $number_array[] = $i;
      }
      $random_number_array = array();
      mt_srand ((double) microtime() * 1000000);
      for($i=0;$i<$count;$i++){
       $random_number      = mt_rand(0,count($number_array)-1);
       $key_to_insert_and_delete = array_search($random_number, $number_array);
       $random_number_array[$i]  = $number_array[$key_to_insert_and_delete];
       array_splice($number_array, $key_to_insert_and_delete, 1);
      }
      // Array $random_number_array with $count random Numbers, between $from and $to
      return $random_number_array;
    }
    ?>
    I hope its helping you.
    Greetings
    Rene Andris
    Here is my Function to generate an Array with unique random Numbers between "$from" and "$to".
    function random_number_array($count, $from, $to){
      for($i=$from;$i<$to;$i++){
      $number_array[] = $i;
      }
      $random_number_array = array();
      mt_srand ((double) microtime() * 1000000);
      for($i=0;$i<$count;$i++){
       $random_number      = mt_rand(0,count($number_array)-1);
       $key_to_insert_and_delete = array_search($random_number, $number_array);
       $random_number_array[$i]  = $number_array[$key_to_insert_and_delete];
       array_splice($number_array, $key_to_insert_and_delete, 1);
      }
      // Array $random_number_array with $count random Numbers, between $from and $to
      return $random_number_array;
    }
    I hope its helping you.
    Greetings
    Rene Andris
    In answer to David and pHp_n00b, about generating a random 6 characters hexadecimal string...
    Well, the easiest solution would be :
    <?php
    $rand = mt_rand(0x000000, 0xffffff); // generate a random number between 0 and 0xffffff
    $rand = dechex($rand & 0xffffff); // make sure we're not over 0xffffff, which shouldn't happen anyway
    $rand = str_pad($rand, 6, '0', STR_PAD_LEFT); // add zeroes in front of the generated string
    echo $rand;
    ?>
    Some examples of generated stuff :
    8514d2
    3188ae
    028f3e
    444397
    1de508
    071662
    You can easily make a function from this code.
    >Running the output of Mersenne Twister through an unkeyed >secure hash is NOT a good way to make it secure, because it'll >still have a relatively small internal state which, if recovered, >would allow reproduction of the keystream. A better idea >would be to encrypt the output with a keyed encryption >algorithm - but if you were going to do that, you wouldn't >need a psuedorandom number generator at all, because a >counter would be just as good.
    Not true. Mersenne Twister has an ENORMOUS amount of internal state - 4992 bits, bigger than practically any cipher's key length. The point of a secure random number generator is that you cannot predict future outputs based on past OUTPUTS, which is why a hash is applied. Clearly you can predict the future output of any pseudorandom number generator if you can acquire the internal state - a better algorithm will never solve this problem. If you use keyed encryption, recovering the key allows you to predict future outputs.
    Shouldn't it be a greater than (>) sign rather than a not equal (!=) sign? Because you're just checking to see if it is exactly six. So if it is 7 it, won't try to fix it. So wouldn't this be better?
    <?
    //....
    if (strlen($random_hex) < "6") // sometimes it returns an only 5, or less, char Hex-Code,
      hexcode();    // so the function has to be repeat
    elseif (strlen($random_hex) > "6") // sometimes it returns 7 or more characters
    //...I don't know how to make it do only six, but your code seems to only check to make sure it doesn't do less than 6; nothing to counter doing more than 6.... so here would be some code to reduce the size back to 6 if it went over.
    else
      echo $random_hex; // returns the Hex-Code
    }
    //...
    ?>
    
    Since many people wrote little scripts to generate random sequences, I'll also give mine (which is slightly faster since it makes use of strlen only once, and uses strings instead of arrays) :
    <?php
    function code($nc, $a='abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789') {
      $l=strlen($a)-1; $r='';
      while($nc-->0) $r.=$a{mt_rand(0,$l)};
      return $r;
    }
    ?>
    
    i did the following, to generate a few random-numbers out of a total amount of numbers, but to create different random-numbers and not double or tripple.
    for example i use it to generate 10 random-pics out of 150, and do shurely generate not twice the same...
    <?php
    $total = 6; // available numbers (of pictures)
    $randanzahl = 6; //number of random-number to generate out of $total
    function checkifdouble($ran,$i) {
        for($j=1; $j<$i; $j++) {
            if($ran[$j]==$ran[$i]) {
                $ergebnis="true";
                break;
            } //endif
            else {
                $ergebnis="false";
            } //endelse
        } //endfor
    return $ergebnis;
    }
    for ($i=1; $i<=$randanzahl; $i++) {
        $ran[$i] = mt_rand(1, $total);
        if ($i>1) {
            while(checkifdouble($ran,$i)=="true") {
                $ran[$i] = mt_rand(1, $total);
                $v=checkifdouble($ran,$i);
                echo($v);
            } //endif
        }
        echo($ran[$i]."<br>");
    } //enfor
    ?>
    this version is easily for debugging and adaption!
    maybe there is a very shorter version...
    You really shouldn't generate a number to determine the _type_ of the char, then the char itself. If security is an issue for you, and you want to maintain as much entropy as possible, you should use a function similar to the one below. Since this seems to be getting repeated over-and-over, I explained (beat into the ground?) the issue on http://www.codeaholics.com/randomCode.php
    The code:
    <?php
    ////
    // Returns a random code of the specified length, containing characters that are
    // equally likely to be any of the digits, uppercase letters, or lowercase letters.
    //
    // The default length of 10 provides 839299365868340224 (62^10) possible codes.
    //
    // NOTE: Do not call wt_srand(). It is handled automatically in PHP 4.2.0 and above
    //    and any additional calls are likely to DECREASE the randomness.
    ////
    function randomCode($length=10){
      $retVal = "";
      while(strlen($retVal) < $length){
        $nextChar = mt_rand(0, 61); // 10 digits + 26 uppercase + 26 lowercase = 62 chars
        if(($nextChar >=10) && ($nextChar < 36)){ // uppercase letters
          $nextChar -= 10; // bases the number at 0 instead of 10
          $nextChar = chr($nextChar + 65); // ord('A') == 65
        } else if($nextChar >= 36){ // lowercase letters
          $nextChar -= 36; // bases the number at 0 instead of 36
          $nextChar = chr($nextChar + 97); // ord('a') == 97
        } else { // 0-9
          $nextChar = chr($nextChar + 48); // ord('0') == 48
        }
        $retVal .= $nextChar;
      }
      return $retVal;
    }
    ?>
    
    Running the output of Mersenne Twister through an unkeyed secure hash is NOT a good way to make it secure, because it'll still have a relatively small internal state which, if recovered, would allow reproduction of the keystream. A better idea would be to encrypt the output with a keyed encryption algorithm - but if you were going to do that, you wouldn't need a psuedorandom number generator at all, because a counter would be just as good.
    <?php
    //
    // Generates a random string with the specified length
    // Chars are chosen from the provided [optional] list
    //
    function simpleRandString($length=16, $list="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"){
      mt_srand((double)microtime()*1000000);
      $newstring="";
      if($length>0){
        while(strlen($newstring)<$length){
          $newstring.=$list[mt_rand(0, strlen($list)-1)];
        }
      }
      return $newstring;
    }
    //
    // Generates a random string with the specified length
    // Includes: a-z, A-Z y 0-9
    //
    function randString($length=16) {
      $newstring="";
      if($length>0) {
        while(strlen($newstring)<$length) {
          $randnum = mt_rand(0,61);
          if ($randnum < 10) {
            $newstring.=chr($randnum+48);
          } elseif ($randnum < 36) {
            $newstring.=chr($randnum+55);
          } else {
            $newstring.=chr($randnum+61);
          }
        }
      }
      return $newstring;
    }
    ?>
    
    Though you might all know this, by now: nonetheless, for 'slow- coaches', such as myself; Remember that mt_rand(), reacts DIFFERENTLY, Depending on your (initial) PHP script declaration.
    For People, such as myself, who have embraced strict-type; if your script is set to "declare(strict_types=1)", at the top of the page (just after opening PHP tag), remember one rule of thumb: 
    If you pass a FLOAT into mt_rand WITHOUT strict-type set to 1, you should be good to go. However, if you HAVE set strict-types to 1, PHP WILL throw an exception:- "mt_rand() expects parameter 1 to be integer, float given". 
    Just so that you don't have to spend a whole hour (like I did), trying to figure out why a script (with mt_rand()) that was working in a separate environment, isn't working now.

    上篇:mt_getrandmax()

    下篇:mt_srand()