A Million Random Digits with 100,000 Normal Deviates1 is a book that was published in 1955 by the RAND Corporation2. The book — that mainly consists of a table with a long sequence of randomly generated digits, as the title suggests — was important in the 20th century in the fields of statistics and random numbers. From 1947 it was constructed by means of an electronic simulation of a roulette wheel that was connected on a computer, and of which the results were meticulously filtered and tested before being added to the table.
The RAND table meant an important break-through in working with random numbers, since a table of this size and coincidence degree was not available before. Apart from the availability in book format, the digits could also be ordered on punch cards. the table was mainly used in statistics and with the experimental purpose of scientific experiments, primarily those that used so-called Monte Carlo-simulations3. The book was one of the last in a sequence of tables with random numbers that were produced from the middle of the twenties until the fifties. From then on, the rise of computers allowed generating pseudo-random numbers in a faster way than they could be looked up in tables.
The book was republished in 2001 (ISBN 0-8330-3047-7) with a new prologue from Michael D. Rich, Executive Vice President of the RAND Corporation. Since then, it has received a lot of funny comments on Amazon.com4:
"I had a hard time getting into this book. The profanity was jarring and stilted, not at all how people really talk."
"Once you get about halfway in, the rest of the story is pretty predictable."
"If you like this book, I highly recommend that you read it in the original binary."
"I would have given it five stars, but sadly there were too many distracting typos. For example: 46453 13987."
"I really liked the '10034 56429 234088' part."
"Frankly the sex scenes were awkward and clumsily written, adding very little of value to the plot."
"For a supposedly serious reference work the omission of an index is a major impediment. I hope this will be corrected in the next edition."
The average readers rewards the book with four stars.
In the random module from the Standard Python Library5 a datatype Random is defined, that can be used to make pseudo-random choices. After all, a computer can never really work randomly, but always has to execute an algorithm that simulates coincidence. Such algorithms calculate, for example, a next choice based on the previous choice. The first time a choice must be made, however, these algorithms need a set start point because there was no previous choice. This is the so-called seed. The example session below illustrates how setting this seed can influence making random choices.
>>> characters = 'UNCOPYRIGHTABLE'
>>> from random import Random
>>> generator = Random()
>>> [generator.choice(characters) for _ in range(10)]
['E', 'Y', 'R', 'A', 'C', 'P', 'T', 'I', 'I', 'L']
>>> [generator.choice(characters) for _ in range(10)]
['I', 'R', 'C', 'I', 'H', 'T', 'H', 'R', 'T', 'L']
>>> generator.seed(3)
>>> [generator.choice(characters) for _ in range(10)]
['O', 'H', 'G', 'C', 'Y', 'E', 'H', 'I', 'T', 'H']
>>> [generator.choice(characters) for _ in range(10)]
['N', 'H', 'U', 'E', 'L', 'I', 'P', 'G', 'O', 'O']
>>> generator.seed(3)
>>> [generator.choice(characters) for _ in range(10)]
['O', 'H', 'G', 'C', 'Y', 'E', 'H', 'I', 'T', 'H']
>>> [generator.choice(characters) for _ in range(10)]
['N', 'H', 'U', 'E', 'L', 'I', 'P', 'G', 'O', 'O']
>>> generator.seed(17)
>>> [generator.choice(characters) for _ in range(10)]
['G', 'R', 'B', 'P', 'Y', 'P', 'C', 'B', 'A', 'A']
>>> [generator.choice(characters) for _ in range(10)]
['G', 'T', 'P', 'N', 'E', 'U', 'O', 'R', 'L', 'A']
In a first instance, a new object of the class Random is made. Because no seed is given at that moment, the system time (the time that the computer reads on its clock) is used as seed. After that, the method choice is used to choose a random object from a given compound object (in this case a random character from the string UNCOPYRIGHTABLE).
Setting a new seed is done by means of the seed methode. To this method, any (immutable) object can be given, that is then used as a new seed. The value None means that the system time will be used as seed. If you watch the session above closely, you will see that setting that setting the same seed as a start base (illustrated here by means of the seed 3) will result in the same sequence being made over and over. Because of this, you can have the randomness of you programs go predictable in a certain sense.
Define a class CharacterGenerator with which a random sequence of characters can be generated in a predictable way. These characters are chosen randomly from the alphabet given. For this, the objects of the class CharacterGenerator must contain at least the following methods:
An initializing method to which a seed must be given. Any (immutable) object may be given as seed, except the value None. If the value None is given as seed, the initializing method must raise an AssertionError with the message no seed given. The initializing method must see to it that every object from the class CharacterGenerator has its own random generator (an object from the class random.Random) and that this is initialized with the given seed. The initialization method also has a second, optional parameter alphabet, to which a string of characters can be given. This forms the alphabet of the characters from which will be chosen randomly. If no explicit value was given to the parameter alphabet, there must be chosen from the digits from the alphabet 0123456789.
A method __repr__ that prints a string representation of the object. This string representation reads as a Python expression that makes a new object from the class CharacterGenerator with the same seed and the same alphabet as the current object. Watch the example session below to find the different shapes of this string representation. Pay attention to the fact that the optional parameter must only be given if the alphabet deviates from the standard alphabet, and that, in this case, the parameter alphabet must be named explicitly.
A method reset to which a seed can be given optionally. If a seed is given to the method, this becomes the new seed of the object. After that, the seed of the object (either the new or the old value) must be used to initialize the coincidence generator of the object.
A method sequence that prints a string that consists of a sequence of randomly chosen characters. Here, the method choice from the coincidence generator of the object is called to select a random character from the alphabet of the object. At the end of the method sequence can be given an optional argument (standard value: 1)that indicates the length of the string that must be printed.
>>> digits = CharacterGenerator(3)
>>> digits
CharacterGenerator(3)
>>> digits.sequence()
'3'
>>> digits.sequence(19)
'9825979190748337887'
>>> digits.sequence(30)
'623286012904047966697251027346'
>>> digits.sequence()
>>> digits
CharacterGenerator(3)
>>> digits.sequence(20)
'39825979190748337887'
>>> digits.sequence(30)
'623286012904047966697251027346'
>>> digits.reset(7)
>>> digits
CharacterGenerator(7)
>>> digits.sequence(20)
'52601815908301661318'
>>> digits.sequence(30)
'609139099603082462819482199351'
>>> CharacterGenerator(None)
Traceback (most recent call last):
AssertionError: no seed was given
>>> spam1 = CharacterGenerator(3, 'SPAM')
>>> spam2 = CharacterGenerator(3, 'SPAM')
>>> spam1.sequence(10)
'PPAMSSMAPP'
>>> spam2.sequence(10)
'PPAMSSMAPP'
>>> spam1
CharacterGenerator(3, alphabet='SPAM')