7.5. Random Numbers¶
7.5.1. Random Numbers¶
The success of randomized algorithms depends on having access to a good random number generator. While modern compilers are likely to include a random number generator that is good enough for most purposes, it is helpful to understand how they work, and to even be able to construct your own in case you don’t trust the one provided. This is easy to do.
First, let us consider what a random sequence is. From the following list, which appears to be a sequence of “random” numbers?
1, 1, 1, 1, 1, 1, 1, 1, 1, …
1, 2, 3, 4, 5, 6, 7, 8, 9, …
2, 7, 1, 8, 2, 8, 1, 8, 2, …
In fact, all three happen to be the beginning of a some sequence in which one could continue the pattern to generate more values. (In case you do not recognize it, the third one is the initial digits of the irrational constant \(e\). Which makes it every bit as deterministic as the other two sequences appear to be.) Viewed as a series of digits, ideally every possible sequence has equal probability of being generated (even the three sequences above, which don’t appear to be “random”). In fact, definitions of randomness generally have features such as:
One cannot predict the next item better than by guessing.
The series cannot be described more briefly than simply listing it out. This is the equidistribution property.
There is no such thing as a random number sequence, only “random enough” sequences. A sequence is pseudo random if no future term can be predicted in polynomial time, given all past terms.
Most computer systems use a deterministic algorithm to select pseudorandom numbers. [1] The most commonly used approach historically is known as the Linear Congruential Method (LCM). The LCM method is quite simple. We begin by picking a seed that we will call \(r(1)\). Then, we can compute successive terms as follows.
where \(b\) and \(t\) are constants. For many purposes, this gives a completely satisfactory series of random numbers. It even has the feature (which often is considered a benefit for testing purposes) of being repeatable by using the same seed.
By definition of the \(\bmod\) function, all generated numbers must be in the range 0 to \(t-1\). Now, consider what happens when \(r(i) = r(j)\) for values \(i\) and \(j\). Of course then \(r(i+1) = r(j+1)\) which means that we have a repeating cycle.
Since the values coming out of the random number generator are between 0 and \(t-1\), the longest cycle that we can hope for has length \(t\). In fact, since \(r(0) = 0\), it cannot even be quite this long. It turns out that to get a good result, it is crucial to pick good values for both \(b\) and \(t\). To see why, consider the following example.
If you would like to write a simple LCM random number generator of your own, an effective one can be made with the following formula.