mt_rand

(PHP 3 >= 3.0.6, PHP 4, PHP 5)

mt_rand -- 生成更好的随机数

说明

int mt_rand ( [int min, int max] )

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

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

例子 1. mt_rand() 范例

<?php
echo mt_rand() . "\n";
echo
mt_rand() . "\n";

echo
mt_rand(5, 15);
?>

上例的输出类似于:

1604716014
1478613278
6

注: 自 PHP 4.2.0 起,不再需要用 srand()mt_srand() 函数给随机数发生器播种,现已自动完成。

注: 在 3.0.7 之前的版本中,max 的含义是 range。要在这些版本中得到和上例相同 5 到 15 的随机数,简短的例子是 mt_rand (5, 11)

参见 mt_srand()mt_getrandmax()rand()


add a note add a note User Contributed Notes
pHp_n00b
26-Sep-2006 10:00
<?php

// Generates a max."6 char" Hex-Code

function hexcode()
{

$min = hexdec("000000"); // result is 0    and sets the min-value for mt_rand
$max = hexdec("FFFFFF"); // result is 16777215 and sets the max-value for mt_rand

$random = mt_rand($min, $max); // creates a radom number between 0 and 16777215

$random_hex = dechex($random); // transforms the random number into a Hex-Code

// now the test, if the result has 6 chars

if (strlen($random_hex) != "6") // sometimes it returns an only 5, or less, char Hex-Code,
  
hexcode();        // so the function has to be repeat
else
   echo
$random_hex; // returns the Hex-Code
}

hexcode();

?>
MagicalTux at ooKoo dot org
25-Aug-2006 08:44
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;
}
?>
arias at elleondeoro dot com
29-May-2006 05:03
Be carefull with: $characters[mt_rand(0, count($characters))];

"If you want a random number between 5 and 15 (inclusive), for example, use mt_rand (5, 15)."

Array index are between 0 and n-1, but mt_rand generates a number between 0 and n!
James
16-Apr-2006 02:02
The Developers Resources article mentioned above should be removed as that site has be down for years. The same article by Gregory Boshoff is available at http://www.phpfive.net/article2.htm
rollerce at gmail dot com
15-Feb-2006 09:38
I know a bunch of you have posted little snippets for random number generation, but here's a nifty (in my opinion) little thing I just wrote to create a 10 digit code with hyphens in it. It also negates the use of 0, O, 1, and I, to avoid confusion. I am ALWAYS willing to accept input so if any of you has suggestions to streamline the code, please let me know.

<?php
    
function GetID($x){     

        
$characters = array("A", "B", "C", "D", "E", "F", "G", "H", "J", "K", "L", "M", "N", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", "2", "3", "4", "5", "6", "7", "8", "9");
        
shuffle($characters);

         for (;
strlen($ReqID)<$x;){
          
$ReqID .= $characters[mt_rand(0, count($characters))];
         }

         return
$ReqID;
        
       }     
    

      
$ReqID .= GetID(3);
      
$ReqID .= "-";
      
$ReqID .= GetID(4);
      
$ReqID .= "-";
      
$ReqID .= GetID(3);

       echo
$ReqID
    
?>
ripat at lumadis dot be
08-Nov-2005 12:38
Yet another snippet to generate a password.
<?php
  $acceptedChars
= 'azertyuiopqsdfghjklmwxcvbnAZERTYUIOPQSDFGHJKLMWXCVBN0123456789';
 
$max = strlen($acceptedChars)-1;
 
$password = null;
  for(
$i=0; $i < 8; $i++) {
  
$password .= $acceptedChars{mt_rand(0, $max)};
  }
  echo
$password;
?>
I have tried several ways of doing it but this simple one seems to be the fastest.
fahri at konse dot de
09-Oct-2005 12:12
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...
phil [underscore] ozil at hotmail dot com
07-Oct-2005 09:13
Quit bothering yourselves.
All it takes to create a secure random-generated password is those three lines:

<?php
$pass
= "";
// Generate a 8 char password
for ($i=0; $i<8; $i++)
 
$pass .= chr(mt_rand(35, 126));
?>

Note:
In this example, the character's ASCII values range from 35 to 126.

For character's ASCII codes please check:
http://www.keller.com/html-quickref/latin1.html
frans-jan at van-steenbeek dot net
03-Oct-2005 10:18
My try at generating a reasonably secure password:

<?php
 
function keygen() {
 
$tempstring =
 
"0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNO
  PQRSTUVWXYZ0123456789abcdefghijklmnopqrstuvwxyzABC
  DEFGHIJKLMNOPQRSTUVWXYZ!?@#$%&*[]{}();:,<>~+=-_
  /|\\"
;
  for(
$length = 0; $length < mt_rand(10, 15); $length++) {
  
$temp = str_shuffle($tempstring);
  
$char = mt_rand(0, strlen($temp));
  
$pass .= $temp[$char];
  }
  return
$pass;
 }
 echo(
keygen());
 echo(
"\n");
?>

This generates a password of an undefined length (in this case, 10 to 15 chars) consisting of numbers, UPPERCASE letters lowercase letters and a set of signs. I have doubled the chance of number and letters to reduce the confusion with my users.
sean at codeaholics dot com
22-Jul-2005 09:31
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;
}
?>
mina86 at nospam dot projektcode dot org
25-May-2005 08:00
Re: solenoid at hotmail dot united dot kingdom

In theory method shown by selenoid can lead to infinite loop. The correct method would be:

<?php
$randomNumbers
= array();
for (
$i = 0; i<30; ++$i) $randomNumbers[] = $i;
shuffle($randomNumbers);
for (
$i = 20; $i<30; ++$i) unset($randomNumbers[$i]);
$randomNumbers = array_values($randomNumbers);
?>

The last two lines may be in some cases removed.
nowhere at where dot net
16-Apr-2005 05:46
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;
}
?>
mskala at ansuz dot sooke dot bc dot ca
24-Jan-2005 07:47
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.
timr at onlinehome dot de
13-Aug-2004 07:24
The correct address of the inventor's FAQ is (http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/efaq.html). They state that Mersenne Twister may be used for cryptography if you do some post-processing:

"Mersenne Twister is not cryptographically secure. (MT is based on a linear recursion. Any pseudorandom number sequence generated by a linear recursion is insecure, since from sufficiently long subsequence of the outputs, one can predict the rest of the outputs.)

To make it secure, you need to use some Secure Hashing Algorithm with MT. For example, you may gather every eight words of outputs, and compress them into one word (thus the length of the output sequence is 1/8 of the original one)."
11-Feb-2004 09:27
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
tmx at ntlworld dot com
07-Dec-2003 05:26
When using this function, it doesn't matter which order the numbers go in.

     mt_rand(16,5)

works just as well as

     mt_rand(5,16)

Which can be useful if you are pulling values from a database, that could be negative or positive.

     mtrand(0,$anyinteger)

Hope this helps someone
daeken_9999 at yahoo dot com
08-Jul-2003 05:44
This is a fixed version of the gaussrand() function defined in a note above.

<?php
function gaussrand()
{
   static
$V2, $V1, $S;
   static
$phase = 0;
   if (
phase == 0)
   {
       while (
$S >= 1 || $S == 0)
       {
          
$V1 = 2 * (rand() / getrandmax()) - 1;
          
$V2 = 2 * (rand() / getrandmax()) - 1;
          
$S = $V1 * $V1 + $V2 * $V2;
       }
      
$X = $V1 * sqrt(-2 * log($S) / $S);
   }
   else
      
$X = $V2 * sqrt(-2 * log($S) / $S);
  
$phase = 1 - $phase;
   return
$X;
}
?>
jsheets at shadonet dot com
05-Jun-2003 04:49
The following function will create a random base64 encoded key, this is very useful for password reset schemes or anything where you want a random string.  To compare the string either compare the base64 encoded value or base64_decode it and compare that.

I do not use md5 because md5 results in only 1-9 and a-f in the string or 32^16 possibilities, by using the extended ASCII table and shuffling the array I am able to get a minimum of 32^127 possibilities with a 32 character string, using a longer string will make your value harder to guess still. A lot of machiens will have 32^255 possibilities in a decoded string.

<?php
function MakeResetKey($min_length = 32, $max_length = 64)
{
  
$key = '';

  
// build range and shuffle range using ASCII table
  
for ($i=0; $i<=255; $i++) {
    
$range[] = chr($i);
   }

  
// shuffle our range 3 times
  
for ($i=0; $i<=3; $i++) {
    
shuffle($range);
   }

    
// loop for random number generation
  
for ($i = 0; $i < mt_rand($min_length, $max_length); $i++) {
    
$key .= $range[mt_rand(0, count($range))];
   }

  
$return = base64_encode($key);

   if (!empty(
$return)) {
     return
$return;
   } else {
     return
0;
   }
}
?>
demogracia at metropoliglobal dot com
03-Mar-2002 04:38
<?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;
}
?>
amcclung at stetson dot edu
19-Apr-2001 04:27
Here's an elegant way of generating a random float value within a certain range:

$range = $upperBound-$lowerBound;
$num = $lowerBound + $range * mt_rand(0, 32767)/32767;

You should now have a floating point number between your $lowerBound (i.e. 0.5) and $upperBound (0.75) values.
mrdlinux at yahoo dot com
21-Jul-2000 01:02
And for those who prefer scaling:

mt_rand() / RAND_MAX * (Max - Min) + Min;