views:

1079

answers:

8

I know that just using rand() is predictable, if you know what your doing, and have access to the server.

I have a project that is HIGHLY dependent on choosing a random that is as unpredictable as possible. So I'm looking for suggestions, either other built in functions, or user functions that can generate a 'better' random number.

I used this to do a little test:

$i=0;
    while($i<10000)
     {
      $rand = rand(0,100);
     if(!isset($array[$rand]))
      {
      $array[$rand] = 1;
      }
     else 
      {
      $array[$rand]++;
      }
     sort($array);
     $i++;
     }

I found the results to be evenly distributed, and there is an odd pattern to the number of times each number is generated.

+1  A: 

Variation on @KG, using the milliseconds since EPOCH as the seed for rand?

jtyost2
I like this suggestion waaaaaaaayyyyy better than mine :-)
KG
+11  A: 

Adding, multiplying, or truncating a poor random source will give you a poor random result. See Introduction to Randomness and Random Numbers for an explanation.

You're right about PHP rand() function. See the second figure on Statistical Analysis for a striking illustration. (The first figure is striking, but it's been drawn by Scott Adams, not plotted with rand()).

One solution is to use a true random generator such as random.org. Another, if you're on Linux/BSD/etc. is to use /dev/random. If the randomness is mission critical, you will have to use a hardware random generator.

Christian Lescuyer
+3  A: 

http://random.org/clients/http/

Kevin
A: 

@Christian Lescuyer - I like random.org, but I decided to stay away from external calls, because if they go down so do I.

I wote this quick, and it seems to produce more randomness.

function myRand($min, $max)
 {
     $array = range($min, $max);
     shuffle($array);
     $i=0;
     while($i<10000)
      {
         $rand = rand($min, $max);
         $array[$rand] = rand($min, $max);
         shuffle($array);
         $i++;
      }
     return $array[rand($min, $max)];
 }
Unkwntech
+1  A: 

By the way, I don't know why people say rand() is weak? It's been updated since PHP4 and seeds before every call.

Kevin
+1  A: 

I would be wary of the impression of randomness: there have been many experiments where people would choose the less random distribution. It seems the mind is not very good at producing or estimating randomness.

There are good articles on randomness at Fourmilab, including another true random generator. Maybe you could get random data from both sites so if one is down you still have the other.

Fourmilab also provides a test program to check randomness. You could use it to check your various myRand() programs.

As for your last program, if you generate 10000 values, why don't you choose the final value amongst the 10 thousand? You restrict yourself to a subset. Also, it won't work if your $min and $max are greater than 10000.

Anyway, the randomness you need depends on your application. rand() will be OK for an online game, but not OK for cryptography (anything not thoroughly tested with statistical programs will not be suitable for cryptography anyway). You be the judge!

Christian Lescuyer
A: 

@Christian Lescuyer I agree about the impression of randomness, however if I run the loop with only 100 iterations I see almost an even distribution of 100 numbers between 1-100. With my myRand function I don't see that even distribution.

Unkwntech
A: 

@Unkwntech,

Your myRand function will return a more random number, but is there a tradeoff in performance?

Instead of 1 call to rand, you call it 20,001 times! not to mention the building of a "potentially" large array with 10,000 accesses.

Also, as Kevin pointed out, PHP 4.2.0 and up auto-seed.

scunliffe