| « Makin' It Fit | Packing Done Right » |
As we learned in Random Stupidity, developers don't really trust rand(), random(), Random.GetNext(), etc. Nor should they. The documentation, after all, clearly states that the function "generates a pseudo-random number." That's right, pseudo. Who wants pseudo?
The neat thing about pseudo-randomness is that, if you think about it -- and you don't think too much about it -- you can actually generate a real random number by pseudo-randomizing a pseudo-randomizer a pseudo-random number of times. It's kind like how two wrongs (either wrongly done for the right reason or rightly done for the wrong reason) make a right. Really, it's simple math.
Jacob's predecessor was well aware of this fact, and devised a very clever way to generate extremely random numbers: by increasing the entropy.
void GenerateRandom(unsigned char Val[16], unsigned long seed)
{
int i;
// Initialize randomizer
srand(seed);
// This really doesn't have enough entropy....
for(i=0;i<(rand() & 16);i++) srand(rand());
// Get the val
for(i=0;i<16;i++) Val[i]=(char)(( rand() >> 7) & 0x00FF);
}
|
The worst thing is that if you happen to run code that tries to increase randomness in an environment where you have a hardware-entropy based random number generator, the code actually *consumes* the entropy!
|
For this reason when I do any form of randomizing in code that may be included in such a system I add ^rand() to the new seed as this factors back in the original randomness |
|
In all seriousness, some people need it forced into them that calling rand() multiple times for one random number makes it LESS random, by massively shortening the time until the prng's sequence repeats.
Taking a stupidly extreme example, a prng that only produces the following two numbers in never-ending sequence when given the seed "42": 6 9 6 9 6 9 6 9... What do you get if you decide that that's not random enough and xor together two numbers every time instead? That's got to be more random right? Look: 6^9=15 6^9=15 6^9=15 6^9=15. We go from 2 numbers repeating to 1 number! How about xoring together a random number of numbers? More random, surely! Look: (6 numbers)(9^6^9^6^9^6) = 15 (9 numbers)(6^9^6^9^6^9^6^9^6) = 6 (9 numbers)(6^9^6^9^6^9^6^9^6) = 6 6 6 6. Lovely, it loops to the same number after the second call! The only way to make it more random is to give it more data (entropy). e.g. take a 1024 element array of numbers and use the value from shitty-prng to step through it (using that primes trick to make sure that you go through all the numbers no matter what the step number is). Suddenly you can get a 1024 number sequence from a prng that only outputs 6 and 9! Or you could just implement or use an existing implementation of the mersenne twister prng, with it's 2^19937 − 1 long number sequence and 64-bit output. Or another, if you need to. Whatever you do, don't try to make a prng of your own without a degree in number theory. |
| « Makin' It Fit | Packing Done Right » |