Hudzilla.org - the homepage of Paul Hudson
Contents > Functions > Mathematics Wish List | Report Bug | About Me ]

4.6.2     Randomisation: rand(), mt_rand(), getrandmax(), mt_getrandmax(), srand(), and mt_srand()

This is NOT the latest copy of this book; click here for the latest version.

int rand ( [int min, int max])

int mt_rand ( [int min, int max])

int getrandmax ( )

int mt_getrandmax ( )

void srand ( [int seed])

void mt_srand ( [int seed])

Sometimes you want to take random actions in your code - it might be to give your web site visitors a different greeting each time they visit, you might be programming a game, or you might be trying to secure data by hashing it. Either way, randomisation is simple and helpful thing to remember, and has just two functions: rand(), and mt_rand().

Both functions do the same thing, and both take the same parameters, so what is the difference between the two? Well, rand() is a basic randomisation function that is very quick but not very "random" - the numbers it generates are slightly more predictable. Mt_rand() on the other hand, is more complicated - the "mt" parts means Mersenne Twister, as that is the name of the randomisation algorithm it uses. Mt_rand() returns much more "random" numbers, but does so at the expense of some speed.

As mentioned, both functions have the same parameters - two optional numbers, for the minimum number to return and the maximum number to return. Either you supply no parameters, which will result in PHP returning a random number between one and a very high number, or you can supply the two parameters. Here is an example:

<?php
    $random
= rand();
    
$randrange = rand(1,10);
    
$mtrandrange = mt_rand(1,100);
?>

Note that the two numbers passed in are inclusive. That is, our $randrange number could be anywhere between 1 and 10 including 1 and 10.

As mentioned, if you do not pass any parameters to your rand() and mt_rand() calls, PHP will generate a random number from 1 to a high number. If you want to find out the maximum number PHP can return from a rand() call, use getrandmax(). There is a similar function, mt_getrandmax() for mt_rand().

Now you know how randomisation works, here is a quick example to show you how you can make use of randomisation to greet web site visitors in various ways:

<?php
    
switch(rand(1,6)) {
        case
1:
            
$greet = 'Hello!'; break;
        case
2:
            
$greet = 'Welcome!'; break;
        case
3:
            
$greet = 'Greetings!'; break;
        case
4:
            
$greet = 'Salutations!'; break;
        case
5:
            
$greet = 'Good day!'; break;
        case
6:
            
$greet = 'Yo!'; break;
    }
    
    print
$greet;
?>

Here we have not bothered assigning the result of rand() to a variable before putting it into the switch statement, but you can do it whichever way is easier for you to read.

One important thing to note is that the speed of randomisation does not depend on the sizes you pass into it - rand() is just as fast in rand(1,3) as it is in rand(1, 10000000). Mt_rand() works just short of 50% slower than rand(), which means you should only be using it if you particularly need the extra randomisation it brings.

To give you an idea of how fast the two run and how using larger values for randomisation makes no difference, try this script:

<?php
    $START
= time();
    for (
$i = 1; $i < 1000000; ++$i) {
        
$j = rand(1,100);
    }
    
$END = time() - $START;
    print
"Short rand() took $END seconds\n";

    
$START = time();
    for (
$i = 1; $i < 1000000; ++$i) {
        
$j = mt_rand(1,100);
    }
    
$END = time() - $START;
    print
"Short mt_rand() took $END seconds\n";

    
$START = time();
    for (
$i = 1; $i < 1000000; ++$i) {
        
$j = rand(1,10000000);
    }
    
$END = time() - $START;
    print
"Long rand() took $END seconds\n";

    
$START = time();
    for (
$i = 1; $i < 1000000; ++$i) {
        
$j = mt_rand(1,10000000);
    }
    
$END = time() - $START;
    print
"Long mt_rand() took $END seconds\n";
?>

Most random number generators require "seeding" - initialising with a starting value - because the numbers they generate are not truly random. Instead, they are known as pseudo-random, meaning that they appear to be random. The seed value is used to generate the first number, the first number is used to generate the second number, the second for the third, etc, meaning that if you always supply the same seed value you will always get the same string of "random" numbers. This is actually advantageous. Many years ago there was a popular game called Elite available on the BBC Micro, where the player was allowed to fly around a large universe of eight galaxies, each with thousands of star systems. Each star system had a very precise number of planets, a distinct economy situation, etc, and yet the entire universe fitted into just 22K of memory. How was this possible? Simple: by providing the same seed to their random number generator, the exact same universe could be generated each time.

Of course, this is a fairly rare situation. More often than not you will want numbers that look random as opposed to numbers that are always the same, and this is where random seeding comes in. If you provide a random number to the random number generator as its seed, you will have a new and original string of random numbers coming out. Does this sound like a chicken and egg situation to you? That is, how do we get the random number to provide to the random number generator? Well, think of what randomness - usually called entropy - you can draw upon in your scripts.

  • The number of files in your temp directory?

  • The number of rows in your database?

  • The time your script was called?

Of all three of these, the latter is potentially the most random - you do not control when your script is called, and you are certainly never likely to have the same script called in the exact same microsecond, so you could use the return value from microtime() as your initial random seed.

The seed function for rand() is srand(), and it takes one parameter - an integer to use as the seed value. If you are using mt_rand(), you should use mt_srand() for seeding. If you recall from earlier, microtime() returns a floating-point number - this is no good for use as the parameter to srand() (or mt_srand() - it is exactly the same), so you need to make it into an integer before use.

Now, as we know that microtime() returns the time in millionths of a second, we can convert its return value to an integer by multiplying it by a million, like this:

srand((double)microtime()*1000000);

The code above should see the standard random number generator fairly well. You can do the same for the Mersenne Twister generator with this code:

mt_srand((double)microtime()*1000000 );

If you want your random number to always generate the same string of numbers, simply supply a seed that is a known value. For example, not matter how often you run it, this next script will always generate the same "random" numbers:

<?php
    mt_srand
(123456);
    echo
mt_rand(1, 100), "\n";
    echo
mt_rand(1, 100), "\n";
    echo
mt_rand(1, 100), "\n";
?>

The last option is just to call srand()/mt_srand() without any parameters at all. In this situation, PHP will attempt to generate a random seed for you - not much good if you want reliably random numbers or if you have a particularly good source of entropy for your seed value, but generally good enough for most people.





<< 4.6.1 Rounding: ceil(), floor(), and round()   4.6.3 Trigonometrical conversion: sin(), cos(), tan(), asin(), acos(), and atan(), deg2rad(), rad2deg() >>
Table of Contents
Want to see this stuff in print? PHP in a Nutshell takes the core topics covered here, adds in thousands of edits from the editorial team and myself, and combines them to make an unbeatable reference for PHP programmers at all levels.



My latest book has hundreds more tips on how to use PHP, Apache, and MySQL, plus Perl, Python, shell scripts, performance tuning, and more!



Top-right shadow
 
Bottom-left shadow Bottom shadow

Comments from other readers
DonT - 07 Sep 2008

Does anyone know if the seed provided by mt_srand() scopes like a variable? e.g. if I run mt_srand() and then call mt_rand inside a function, will it be seeded by the new seed?

A PHP User - 07 Sep 2008

PHP noob: This is exactly what has been running through my mind for few weeks. Can't seem to find the answer yet :(

PHP noob - 07 Sep 2008

"The mt_rand() function ... [snip] ... will produce random numbers four times faster than what the average libc rand() provides." -- The PHP manual

Since mt_rand() is both faster and "more random" than rand() I see no reason to use rand() at all.
I understand mt_rand() can not be used for cryptography. But is rand() any better in this respect?

deathgod - 07 Sep 2008

talk about wierd results:

Short rand() took 5 seconds
Short mt_rand() took 4 seconds
Long rand() took 3 seconds
Long mt_rand() took 3 seconds

Sancho - 07 Sep 2008

quote: "Here's an easy code to make an aleatory background color, it could be used also for the color letter, and all those things. This book is very usefull.

<?php
$random2=mt_rand(0,999999);
print "<body bgcolor=" . $random2 . ">";
?>"

When you put "0x" in front of the numbers it is possible to get the rest of the colors too :-) GREAT BOOK!

Sancho - 07 Sep 2008

quote: "Here's an easy code to make an aleatory background color, it could be used also for the color letter, and all those things. This book is very usefull.

<?php
$random2=mt_rand(0,999999);
print "<body bgcolor=" . $random2 . ">";
?>"

When you put "0x" in front of the numbers it is possible to get the rest of the colors too :-) GREAT BOOK!

hebrego - 07 Sep 2008

Here's an easy code to make an aleatory background color, it could be used also for the color letter, and all those things. This book is very usefull.

<?php
$random2=mt_rand(0,999999);
print "<body bgcolor=" . $random2 . ">";
?>

Tom - 07 Sep 2008

A random content script:
<?php
$content = array(
1 => "Hello",
2 => "Hi",
3 => "Welcome",
4 => "Get down on the ground with your hands up. You have 10 seconds to comply.",
);
$rand = mt_rand(1, count($content));
print $content[$rand];
?>

Arthur Steenkist - 07 Sep 2008

As of PHP 4.2.0, there is no need to seed the random number generator with srand() or mt_srand() as this is now done automatically. (PHP Manual)

ravi - 07 Sep 2008

Explanation is fine.it was very helpful to me.thanks

tyro - 07 Sep 2008

I tried the switch/case example, missed one single quote after Salutations! and it messed the whole script up. Just returned a blank page. Spent 20 minutes trying to figure out what I did wrong...LOL

1 little mistake...wow

chrizPadilay - 07 Sep 2008

yes you're right Daniel...but it's pretty obvious and common sense that he means "no matter"...

Daniel Phin - 07 Sep 2008

For example, not matter how often you run it

typo

i guess its supposed to be "example, no matter" ??

A PHP User - 07 Sep 2008

I still do not understand what the difference between calling srand with no paramters and not calling it at all.



Add comment
Please note that by posting a comment here you are committing it to the public domain. This is important so that others can make use of your code themselves, and also so that I can incorporate helpful notes directly into the main text. Comments are limited to 2000 characters in length.

If you are reporting an error in the content, please tell me directly.

Your name/email address:
Your comment:
 
Now, in order to verify that you're a real person, please answer this simple question: what is seven plus ten?
The answer is:
(please write in
numbers, eg 19)


Top-right shadow
 
Bottom-left shadow Bottom shadow