Random Number Generator
Question: Given an unbiased PRNG which returns values in the range 0-5, how could you use this function to produce unbiased random numbers in the range 0-7.
Answer: Most people immediately think that they could run the Rand5() twice and return the sum mod 8 however this doesn't produce unbiased results. To get unbiased results every possible result needs to have the same probability.
Consider what the numbers 0-5 look like in binary:
0 = 000
1 = 001
2 = 010
3 = 011
4 = 100
5 = 101
Notice that we have 6 values in total. This is nice and even and will help us no doubt. Now look at the least-significant bits (LSB) of these 6 values. Three have a one and three have a zero. i.e. 0s and 1s have an equal likelihood of appearing in the LSB of the returned random number. The same cannot be said of the other 2 columns.
Now let us add 6 and 7 to our binary table:
0 = 000
1 = 001
2 = 010
3 = 011
4 = 100
5 = 101
6 = 110
7 = 111
This table shows the binary representation of all possible values that could be returned from the function we need to produce - Rand7(). Examining the distribution of zeros and ones in each column we can see that every column have an even distribution of 0s and 1s. So we can produce Rand7() as follows:
static uint Rand7()
{
return (uint)(((Rand5() & 1) << 2) + ((Rand5() & 1) << 1) + (Rand5() & 1));
}
What this is doing is calling the Rand5() function 3 times, masking off the LSB which we know will be evenly distributed between 0s and 1s, and shifting them into each of the 3 bit positions, then converting the resulting binary representation to an unsigned integer. The result is an unbiased pseudo-random drawing from the range 0-7 inclusive.
01 Jan 2009 Damien Wintour 0 comments







