views:

1172

answers:

9

Hello!

I heard that PHP's rand() function doesn't give good random numbers. So I started to use mt_rand() which is said to give better results. But how good are these results? Are there any methods to improve them again?

My idea:

<?php
function rand_best($min, $max) {
    $generated = array();
    for ($i = 0; $i < 100; $i++) {
        $generated[] = mt_rand($min, $max);
    }
    shuffle($generated);
    $position = mt_rand(0, 99);
    return $generated[$position];
}
?>

This should give you "perfect" random numbers, shouldn't it?

I hope you can help me. Thanks in advance!

A: 

There is no such thing as a "perfect" random number. No matter what subjective definition of "perfect" you have. You can only achieve pseudo-random.

I was simply trying to point you in the right direction. You asked a question about perfect random numbers, even if perfect was in quotes. And yes, you can improve randomness. You can even implement heuristic or "natural" algorithms, such ideas like "atmospheric noise" -- but still, you're not perfect, not by any means.

Sev
But even if there are only pseudo-random numbers, you can improve the randomness, can't you?
+2  A: 
<?php
  function random_number(){
      return 4; // return generated number
                // guaranteed to be random
  }
  ?>

All joking aside, you're getting into a philosophical question of what is "random" or what is "best". Ideally you'd want your random numbers to have few patterns in them over the course of your procedure. Generally system time is used as the seed, but I've also used the previous random number as the seed, the previous random numberth ago as the seed. The problem is, with a powerful enough computer and full knowledge of the hardware running, and generator function, you would be able to predict the entire set of numbers generated. Thus if you had a powerful enough computer (some people put God into this category) that knew all possible variables and functions of the universe you would then be able to predict every event that happened or will happen. Most random number generators are fine on their own but if you know someone who can see the patterns, more likely they are like the guy in Beautiful Mind and you should get them checked into a clinic.

By popular demand :D

mandroid
Not sure people who don't read xkcd would get the joke. Probably would've been better linking it.
Davy8
I should downvote you for not linking it.
Unkwntech
instead I'll just insert the image
Unkwntech
At first, I didn't understand the joke. But after seeing the comic on the linked page, I did, of course. :D
+11  A: 

Pseudorandom number generators (PRNG) are very complex beast.

There are no real "perfect" random number generators -- in fact the best that can be done from mathematical functions are pseudorandom -- they seem random enough for most intents and purposes.

In fact, performing any additional actions from a number returned by a PRNG doesn't really increase its randomness, and in fact, the number can become less random.

So, my best advice is, don't mess around with values returned from a PRNG. Use a PRNG that is good enough for the intended use, and if it isn't, then find a PRNG that can produce better results, if necessary.

And frankly, it appears that the mt_rand function uses the Mersenne twister, which is a pretty good PRNG as it is, so it's probably going to be good enough for most casual use.

Edit

There was a question in the comments why performing operations on a random number can make it less random. For example, some PRNGs can return more consistent, less random numbers in different parts of the bits -- the high-end can be more random than the low-end.

Therefore, in operations where the high-end is discarded, and the low end is returned, the value can become less random than the original value returned from the PRNG.

I can't find a good explanation at the moment, but I based that from the Java documentation for the Random.nextInt(int) method, which is designed to create a fairly random value in a specified range. That method takes into account the difference in randomness of the parts of the value, so it can return a better random number compared to more naive implementations such as rand() % range.

coobird
How can it become 'less random'?
karim79
karim: Since all PRNGs are based on calculations which just generate apparently random numbers there are certain drawbacks. In principle generating "random" numbers goes against everything a computer can do, since computers are—by design—deterministic machines. Depending on which calculations are performed on the numbers to generate random bits there are some that exhibit statistically good randomness and some that do not. That depends on your generator, though. LCGs have weak low bits, other types have weak high bits, others even don't exhibit any weakness. It is a very complex topic.
Joey
coobird: Java's Random.nextInt(int) does _not_ cater for weaker bits. What it does is eliminating bias due to the modulus operation which would prefer smaller values. It took me two days to understand why it works but it does it very elegantly. But 600 chars is too short for this. The part that discards low-order bits (because of less randomness) is done in Random.next(int): return (int)(seed >>> (48 - bits)). As you can see, at most 32 of the 48 bits of the LCG are returned there which does a good job eliminating the "weak" low-order bits.
Joey
Thank you very much. So I'll just use mt_rand(). I thought there are some possibilities to improve the randomness but apparently there aren't.
marco: If in doubt, just don't. Meddling with pseudo-random numbers needs great care to not ruin the result. If you know nothing about what you are doing you most likely make things worse.
Joey
+7  A: 

I'm not sure that what you've done "improves" the randomness. From what I can understand you generate 100 random numbers and then randomly pick one of them.

From what I can remember from my probability course, this probably doesn't increase the randomness, as if there is an underlying bias in the generator function (mt_rand()), then it will still be reflected somehow in the output.

Peter
You've understood it correctly. Thanks for your answer. Now I know that I can't improve the randomness with further calculations.
+7  A: 

In what way is mt_rand() "bad"?

For example: If it favors a certain number. Lets say mt_rand(1, 10) favours low numbers in the range, ie "1" and "2" occurs on average more than 10% each. Then your "improvement" would still suffer from the same problem.

Selecting a random number out of a faulty sequence will still be faulty.

truppo
Yep, this is exactly what I was thinking.
Peter
Thank you, well explained.
A: 

It is not possible to generate true random numbers, the best you can hope for is pseudo-random which is what rand() provides, your function is no closer to random then rand(). Take a look at this http://en.wikipedia.org/wiki/Random_number_generator

Unkwntech
You mean mt_rand(), the rand() function in php has been shown to be flawed.
Gerry
mt_rand() and rand() are no more flawed then any other psuedo-RNG, as far as I know.
Unkwntech
The difference lies in the algorithm and provable statistical properties of the random numbers. And rand() does *not* suffice for many applications. Furthermore, the Mersenne Twister is fast enough and generates much higher-quality numbers so for people without deep knowledge of the field you can safely suggest MT19937 instead of the built-in rand().
Joey
A: 

If you don't like PHP's built in rand(), you probably shouldn't use their built-in shuffle() either, since it seems to be built on their rand().

I am halfway sure the "industry standard" shuffle now is the Fisher-Yates shuffle.

Mark Rushakoff
A: 

It all depends what for you need that random number :) For me ShuffleBag is the best one :)

Thinker
A: 

I'm guessing you're worried about the distribution of mt_rand(). I have tested it and it is very level and both bounds are inclusive.

I added my test to the comments of the documentation for mt_rand() on the php manual, but it was removed by a silly moderator due to politics that are too long winded to go into here.

Gerry
I should also note that for true random numbers (if there is such a thing) they will become more evenly distributed as the number of iterations approaches infinity. While this is also true with mt_rand(), from my tests it seems on average to be a lot quicker at gaining more even distribution.
Gerry
That all depends on which distribution the random numbers follow. It it's a uniform distribution, then yes. But there are specialized PRNGs that generate random numbers in other distributions as well (normal, exponential, ...) which saves you the effort of altering the distribution (as for some distributions there are no easy/good/efficient ways). When looked upon from only one dimension, rand() and mt_rand() should look fairly the same in terms of "randomness". It's starting from 3 dimensions upward where things get fun with LCGs :-)
Joey