4.4 Random-Number Generation

We now take a brief diversion into a popular type of programming application—simulation and game playing. You can introduce the element of chance via the Python Standard Library’s random module.

Rolling a Six-Sided Die

Let’s produce 10 random integers in the range 1–6 to simulate rolling a six-sided die:

In [1]: import random

In [2]: for roll in range(10):
   ...:     print(random.randrange(1, 7), end=' ')
   ...:
4 2 5 5 4 6 4 6 1 5

First, we import random so we can use the module’s capabilities. The randrange function generates an integer from the first argument value up to, but not including, the second argument value. Let’s use the up arrow key to recall the for statement, then press Enter to re-execute it. Notice that different values are displayed:

In [3]: for roll in range(10):
   ...:     print(random.randrange(1, 7), end=' ')
   ...:
4 5 4 5 1 4 1 4 6 5

Sometimes, you may want to guarantee reproducibility of a random sequence—for debugging, for example. At the end of this section, we’ll show how to do this with the random module’s seed function.

Rolling a Six-Sided Die 6,000,000 Times

If randrange truly produces integers at random, every number in its range has an equal probability (or chance or likelihood) of being returned each time we call it. To show that the die faces 1–6 occur with equal likelihood, the following script simulates 6,000,000 die rolls. When you run the script, each die face should occur approximately 1,000,000 times, as in the sample output.

Fig. 4.1 | Roll a six-sided die 6,000,000 times.

 1 # fig04_01.py
 2 """Roll a six-sided die 6,000,000 times."""
 3 import random
 4
 5 # face frequency counters
 6 frequency1 = 0
 7 frequency2 = 0
 8 frequency3 = 0
 9 frequency4 = 0
10 frequency5 = 0
11 frequency6 = 0
12
13 # 6,000,000 die rolls
14 for roll in range(6_000_000):  # note underscore separators
15     face = random.randrange(1, 7)
16
17     # increment appropriate face counter
18     if face == 1:
19         frequency1 += 1
20     elif face == 2:
21         frequency2 += 1
22     elif face == 3:
23         frequency3 += 1
24     elif face == 4:
25         frequency4 += 1
26     elif face == 5:
27         frequency5 += 1
28     elif face == 6:
29         frequency6 += 1
30
31 print(f'Face{"Frequency":>13}')
32 print(f'{1:>4}{frequency1:>13}')
33 print(f'{2:>4}{frequency2:>13}')
34 print(f'{3:>4}{frequency3:>13}')
35 print(f'{4:>4}{frequency4:>13}')
36 print(f'{5:>4}{frequency5:>13}')
37 print(f'{6:>4}{frequency6:>13}')
Face     Frequency
   1        998686
   2       1001481
   3        999900
   4       1000453
   5        999953
   6        999527

The script uses nested control statements (an ifelif statement nested in the for statement) to determine the number of times each die face appears. The for statement iterates 6,000,000 times. We used Python’s underscore (_) digit separator to make the value 6000000 more readable. The expression range(6,000,000) would be incorrect. Commas separate arguments in function calls, so Python would treat range(6,000,000) as a call to range with the three arguments 6, 0 and 0.

For each die roll, the script adds 1 to the appropriate counter variable. Run the program, and observe the results. This program might take a few seconds to complete execution. As you’ll see, each execution produces different results.

Note that we did not provide an else clause in the ifelif statement. Exercise 4.1 asks you to comment on the possible consequences of this.

Seeding the Random-Number Generator for Reproducibility

Function randrange actually generates pseudorandom numbers, based on an internal calculation that begins with a numeric value known as a seed. Repeatedly calling randrange produces a sequence of numbers that appear to be random, because each time you start a new interactive session or execute a script that uses the random module’s functions, Python internally uses a different seed value.1 When you’re debugging logic errors in programs that use randomly generated data, it can be helpful to use the same sequence of random numbers until you’ve eliminated the logic errors, before testing the program with other values. To do this, you can use the random module’s seed function to seed the random-number generator yourself—this forces randrange to begin calculating its pseudorandom number sequence from the seed you specify. In the following session, snippets [5] and [8] produce the same results, because snippets [4] and [7] use the same seed (32):

In [4]: random.seed(32)

In [5]: for roll in range(10):
   ...:     print(random.randrange(1, 7), end=' ')
   ...:
1 2 2 3 6 2 4 1 6 1
In [6]: for roll in range(10):
   ...:     print(random.randrange(1, 7), end=' ')
   ...:
1 3 5 3 1 5 6 4 3 5
In [7]: random.seed(32)

In [8]: for roll in range(10):
   ...:     print(random.randrange(1, 7), end=' ')
   ...:
1 2 2 3 6 2 4 1 6 1

Snippet [6] generates different values because it simply continues the pseudorandom number sequence that began in snippet [5].

Self Check

  1. (Fill-In) The element of chance can be introduced into computer applications using module      .
    Answer: random .

  2. (Fill-In) The random module’s       function enables reproducibility of random sequences.
    Answer: seed .

  3. (IPython Session) Requirements statement: Use a for statement, randrange and a conditional expression (introduced in the preceding chapter) to simulate 20 coin flips, displaying H for heads and T for tails all on the same line, each separated by a space.
    Answer:

    In [1]: import random
    
    In [2]: for i in range(20):
       ...:     print('H' if random.randrange(2) == 0 else 'T', end=' ')
       ...:
    T H T T H T T T T H T H H T H T H H H H
    

In snippet [2]’s output, an equal number of Ts and Hs appeared—that will not always be the case with random-number generation.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.135.209.249