TalkPHP (http://www.talkphp.com/forums.php)
-   General (http://www.talkphp.com/general/)
-   -   How Rdoanm is Rondam? (http://www.talkphp.com/general/1167-how-rdoanm-rondam.html)

 Wildhoney 09-19-2007 09:38 AM

How Rdoanm is Rondam?

Being able to issue random strings or integers in programming has long been a topic of fascination. Although this article doesn't attempt to tackle the profound questions on randomisation because, well, I'm not at all good at maths, it does teach you how you can make the possibilities of getting the same random number so slim it's almost impossible.

The truth is that nothing is truly random, everything is based on something. For instance, I could throw out the word "Mash Potato" to you right now. Is it totally random? Or is it because I had it for my tea 5 nights ago? I could even pick out the 5 of diamonds from a stack of cards, seemingly totally random, but my option was based on something in my mind telling me to choose the card from that position.

The same goes for a computer. A computer can never be truly random. It can only throw out a random value based on the information it is fed. I could write the longest set of functions in the world in my PHP script, but it'd still boil down to certain factors. I've given it an IP address and it's given me 3 random numbers based on that IP address back to me, it's not random, it's just based on what the function does to return those 3 numbers to me.

All the philosophical stuff aside, however, we can return a fairly random string. Take the following example and ascertain whether or not it'd be viable in a small to medium sized application.

PHP Code:

``` \$iN = rand(0, 9);  ```
`\$iN` is always going to be anywhere from 0 to 9. On the 11th execution of the script it is inevitable that you will have had that number already. I'd be very surprised if it would take to the 11th go to repeat a number. The odds are stacked well against it as your chance decreases by 1 upon every single execution.

Although `rand();` may be a fairly quick way to generate a random number, it is not the best way on its own. For example `rand(1000, 2000);` would be a better solution but again your chances are still very limited. After all, the numbers we count in are base 10. That is: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9. Whereas a numbering system such as hex (hexadecimal) is a base 16 numbering system: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, A, B, C, D, E, F. That way a function that returned a random value would give you more possibilities in hexadecimal then in decimal. To sum it up, a base 2 system such as binary would be absolutely useless.

So what's the solution? In the interest of usability, you must find a nice spot between giving yourself a lot of possibilities with a very slim chance of repetition, and speed. Take the following as an example:

PHP Code:

``` \$szRand = substr(str_shuffle(md5(\$_SERVER['REMOTE_ADDR'] . rand(1000, 9999))), 0, 5);  ```
This will give you a 5 character return value based on the base 16 numbering system. The line will shuffle the user's IP address with a random number from 1000 to 9999. It is a quick randomisation technique that which will give you a lot of possibilities.

However, there is another function worth mentioning in PHP that could help us in our randomisation dilemma, `mktime()` is the amount of seconds between the Unix epoch (January 1st, 1970 - 00:00:00 GMT) and the current date specified via the 2nd argument.

Note: The second option for mktime() is optional. If unspecified then mktime() will return the amount of seconds between Unix epoch and the current time and date.

This `mktime()` function will be unique every second. The amount of seconds will never repeat themselves but merely continue on and on into the future. This will give us an unbelievably slim possibility that we will have repeating numbers. For it to occur we would have to have generated the exact random number at the exact same second in time. I'm sure you can deduce that just about everything is on our side. Thus:

PHP Code:

``` \$szRand = md5(mktime() . rand(0, 25));  ```
Although we're back to a narrow 0 to 25 random integer, we have increased our chances of not repeating a number by thousands. For us to get the same random number now, the function would have to output the same number from the `rand(0, 25);` at the exact same second. You may use `substr()` to cut down the value somewhat, but just bear in mind that cutting `mktime()` down will increase the chance of the value being repeated again.

The way the folks at YouTube do it with their random values for video links, is by storing the unique ID in the database and then checking to see if it is unique. If it isn't, generate a new 1 until it's unique. Remember though, nothing is truly unique, without having anything to check the random value against we can only make the possibility of repetition so narrow and unlikely it's highly impossible.

 Karl 09-19-2007 11:34 AM

Good article. A small mention of srand and mt_srand (mt_round being the preferred method) may have been beneficial as they allow you to seed the random number generator; the latter using the Mersenne Twister algorithm.

 Salathe 09-19-2007 01:14 PM

Regarding seeding the random number generator:
Quote:
 Note: 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. Source: http://php.net/srand

 Karl 09-19-2007 01:32 PM

Well in that case, my only observation would be to suggest `mt_rand` as an aternative to rand - for one, it's apparently upto four times quicker than `rand`

http://uk.php.net/mt_rand

 All times are GMT. The time now is 01:46 PM.