Skip to main content
Editor

Random Values and Simulations: RANDOM(a, b) in Python

Beginner35 min3 exercises45 XP
0/3 exercises

A random value is a number a program cannot predict ahead of time, and simulations use random values to copy the uncertainty of the real world, from a coin toss to the way a rumor travels through a school. Games use them to shuffle cards, and weather apps use them to try out thousands of possible tomorrows.

How does RANDOM(a, b) work?

On the exam, RANDOM(a, b) returns a random whole number from a to b, including both `a` and `b`. Every value in that range is equally likely. So RANDOM(1, 6) acts like a six-sided die: it can return 1, 2, 3, 4, 5 or 6, each one-sixth of the time.

Python's version is random.randint(a, b) from the random module, and it also includes both ends. Because the values are random, each run of the program may give a different result. Run this box a few times:

Ten rolls of a die
import random
rolls = []
for _ in range(10):
rolls.append(random.randint(1, 6)) # RANDOM(1, 6)
print("Ten dice rolls:", rolls)
print("Smallest:", min(rolls), "Largest:", max(rolls))
Output
Ten dice rolls: [4, 5, 3, 1, 2, 5, 5, 3, 3, 2]
Smallest: 1 Largest: 5

That has a side effect for testing. A program that uses random values can work on one run and fail on the next, for example when a rare value such as the top of the range finally comes up. So random code is tested by running it many times and checking every result, which is how the exercises at the end of this page check your functions.

Different results every run are great for games but awkward when you are hunting a bug. random.seed(n) starts the random number generator from a fixed point, so the same "random" numbers come out every time:

A seed makes random results repeatable
import random
for attempt in [1, 2]:
random.seed(2027)
rolls = []
for _ in range(5):
rolls.append(random.randint(1, 6))
print(f"Run {attempt}:", rolls)
Output
Run 1: [1, 4, 1, 1, 6]
Run 2: [1, 4, 1, 1, 6]

Which values can a random expression produce?

Exam questions often ask which values an expression with RANDOM could produce. Work it out in two steps: list every value RANDOM can return, then apply the rest of the expression to each one.

  • RANDOM(1, 4) * 2 turns 1, 2, 3, 4 into 2, 4, 6, 8. Odd numbers like 5 are impossible.
  • RANDOM(0, 3) + 5 gives 5, 6, 7 or 8.
  • RANDOM(1, 10) MOD 3 gives only 0, 1 or 2, because those are the only possible remainders.
  • RANDOM(1, 6) + RANDOM(1, 6) gives 2 to 12, but those totals are not equally likely.
  • The last one surprises people. There are 36 equally likely ways two dice can land, and six of them add up to 7, but only one adds up to 2. This program lists every case instead of guessing:

    Every possible value, listed
    doubled = []
    for r in range(1, 5): # every value RANDOM(1, 4) can return
    doubled.append(r * 2)
    print("RANDOM(1, 4) * 2 can be:", doubled)
    remainders = []
    for r in range(1, 11): # every value RANDOM(1, 10) can return
    if r % 3 not in remainders:
    remainders.append(r % 3)
    print("RANDOM(1, 10) MOD 3 can be:", sorted(remainders))
    ways = {}
    for first in range(1, 7):
    for second in range(1, 7):
    total = first + second
    ways[total] = ways.get(total, 0) + 1
    print("Two dice, ways to make each total out of 36:")
    for total in range(2, 13):
    print(f"{total:>3}: {'#' * ways[total]} {ways[total]}")
    Output
    RANDOM(1, 4) * 2 can be: [2, 4, 6, 8]
    RANDOM(1, 10) MOD 3 can be: [0, 1, 2]
    Two dice, ways to make each total out of 36:
      2: # 1
      3: ## 2
      4: ### 3
      5: #### 4
      6: ##### 5
      7: ###### 6
      8: ##### 5
      9: #### 4
     10: ### 3
     11: ## 2
     12: # 1

    Comparisons with RANDOM make events happen with a chosen chance. RANDOM(1, 100) ≤ 30 is true for 30 of the 100 equally likely values, so it is true 30% of the time. A game can use it for "a 30% chance of rain" or "a 1 in 4 chance of a bonus" (RANDOM(1, 4) = 1).

    What is a simulation?

    A simulation is a program that imitates something from the real world: a disease spreading, cars at a traffic light, a ball bouncing. It is an abstraction: a simpler version of a more complex object or event, built for one specific purpose.

    A simulation keeps the state of the thing it imitates in variables, and those values keep changing as it runs. In a traffic simulation, the number of cars waiting at each light goes up and down every simulated second.

    People use simulations to draw conclusions about real events without the limits of the real world. They are most useful when a real experiment is impractical because it is:

  • too big: two galaxies colliding;
  • too small: molecules in a new battery;
  • too fast: a car crash that is over in a tenth of a second;
  • too slow: a forest growing for 200 years;
  • too expensive: building three versions of a bridge to see which lasts;
  • too dangerous: letting a wildfire burn or a virus spread to see what happens.
  • You meet simulations more often than you might think. Weather forecasts run a model of the atmosphere many times with slightly different starting values. Flight simulators let pilots practise engine failures that would be far too risky to try in a real plane. Sports video games simulate a season to predict standings.

    The real world is full of variation. Customers do not arrive exactly every 2 minutes, and a basketball player does not hit exactly 7 of every 10 free throws. Random number generators let a simulation copy that variability.

    How close does a simulation get to the truth?

    A fair coin lands heads half the time, but 10 flips can easily give 7 heads. The more times a simulation runs, the closer its results usually get to the true chance. Watch the share of heads settle as the number of flips grows:

    Coin flips settle near 50%
    import random
    random.seed(7)
    heads = 0
    flips = 0
    for checkpoint in [10, 100, 1000, 10000, 100000]:
    while flips < checkpoint:
    if random.randint(1, 2) == 1: # RANDOM(1, 2) = 1 counts as heads
    heads += 1
    flips += 1
    print(f"{flips:>7} flips: {heads / flips:.1%} heads")
    Output
         10 flips: 70.0% heads
        100 flips: 51.0% heads
       1000 flips: 51.1% heads
      10000 flips: 50.5% heads
     100000 flips: 50.2% heads

    You can also check a simulation against something you know for certain. Here 36,000 simulated throws of two dice are compared with the exact counts from the 36 ways the dice can land (each way should come up about 1,000 times):

    Simulated dice against the exact answer
    import random
    random.seed(3)
    THROWS = 36000
    counts = {}
    for _ in range(THROWS):
    total = random.randint(1, 6) + random.randint(1, 6)
    counts[total] = counts.get(total, 0) + 1
    exact_ways = [1, 2, 3, 4, 5, 6, 5, 4, 3, 2, 1] # totals 2 to 12
    print("Total Simulated Exact")
    for total in range(2, 13):
    exact = exact_ways[total - 2] * THROWS // 36
    print(f"{total:>5} {counts[total]:>9} {exact:>5}")
    Output
    Total  Simulated  Exact
        2       1002   1000
        3       2023   2000
        4       3080   3000
        5       4078   4000
        6       4959   5000
        7       5857   6000
        8       4915   5000
        9       4049   4000
       10       2996   3000
       11       1981   2000
       12       1060   1000

    The simulated column is close to the exact one but never identical. That is normal: a simulation gives an estimate, and more runs give a better one.

    What does a simulation leave out?

    Building a simulation means removing details and simplifying how things work. A flu simulation might treat every student as equally likely to catch the flu, ignore weekends, and pretend nobody gets a vaccine. Without simplifying, nobody could finish writing the program, and it would run far too slowly.

    Those choices have a cost. A simulation can contain bias that comes from which real-world parts were included and which were left out. A cafeteria simulation that only models students who buy lunch, and leaves out teachers and visitors, will predict shorter lines than the real ones. The bias is not random noise that more runs can average away; it pushes every run in the same direction.

    So treat a simulation's answer as evidence, and ask what it left out. Compare it with real data whenever you can.

    How do simulations help test ideas?

    Simulations make it quick to form a guess (a hypothesis), test it, and refine it. Change one value, run again, and compare. Here is a rumor in a school of 500 students. On day 0, one student knows it. Every day, each student who knows tells a few students picked at random (some of whom already know). The hypothesis: if each student tells only 1 person a day instead of 2, the rumor takes about twice as long.

    A rumor spreading through a school
    import random
    SCHOOL_SIZE = 500
    def spread(tells_per_day):
    knows = [False] * SCHOOL_SIZE
    knows[0] = True # day 0: one student starts the rumor
    history = [1]
    while history[-1] < SCHOOL_SIZE and len(history) < 100:
    for _ in range(history[-1] * tells_per_day):
    knows[random.randint(0, SCHOOL_SIZE - 1)] = True
    history.append(knows.count(True))
    return history
    random.seed(12)
    for tells in [2, 1]:
    history = spread(tells)
    print(f"Telling {tells} a day: everyone knows by day {len(history) - 1}")
    print(" first week:", history[:8])
    Output
    Telling 2 a day: everyone knows by day 10
      first week: [1, 3, 9, 26, 71, 182, 350, 458]
    Telling 1 a day: everyone knows by day 15
      first week: [1, 2, 4, 8, 16, 31, 62, 108]

    In the run above, everyone knows by day 10 when students tell 2 people a day, and by day 15 when they tell 1. Halving the telling made the rumor take about 50% longer, not twice as long, so the hypothesis gets refined. The first week shows why: the early days grow much faster with 2 people a day, but at the end the last few students take a while to hear the rumor either way, because random picks keep landing on people who already know. A next hypothesis to test: what if each student stops telling after three days?

    This model is full of simplifications. Real students talk mostly to friends, not to random people, and some never pass a rumor on. Each of those details could be added, and each choice could push the answer one way or the other.

    Check your understanding

    Which of the following lists every value that RANDOM(2, 5) can return?

    Answers

    Which of the following describes all the values this code segment could display?

    x ← RANDOM(1, 4) * 2 + 1
    DISPLAY(x)
    Answers

    A game should give a player a bonus with a 25% chance. Which of the following conditions are true exactly 25% of the time? Select two answers.

    Select 2 answers.

    Answers

    Which of the following lists all the values this code segment could display?

    heads ← 0
    REPEAT 3 TIMES
    {
    IF(RANDOM(1, 2) = 1)
    {
    heads ← heads + 1
    }
    }
    DISPLAY(heads)
    Answers

    For which of the following tasks would a computer simulation be most useful instead of a real-world experiment?

    Answers

    A city builds a simulation of traffic on a planned bridge. To keep it simple, the simulation treats every vehicle as a car and leaves out buses and trucks. Which of the following is the most likely consequence of this choice?

    Answers

    Which of the following statements about simulations are true? Select two answers.

    Select 2 answers.

    Answers

    Practice exercises

    Roll Any Die
    Write Code

    Write roll(sides) that returns a random whole number from 1 to sides, including both, like RANDOM(1, sides) on the exam. Use random.randint.

    roll(6)   ->  any of 1, 2, 3, 4, 5, 6
    roll(1)   ->  1
    import random
    def roll(sides):
    # Return a random whole number from 1 to sides
    pass
    A Chance of Rain
    Write Code

    Write chance(percent) that returns True about percent percent of the time and False the rest of the time. Pick a random whole number from 1 to 100 and compare it with percent.

    chance(0) must never return True, and chance(100) must always return True.

    import random
    def chance(percent):
    # Return True about percent percent of the time
    pass
    Board Game Turns
    Write Code

    A game piece starts on square 0. Each turn it moves forward by one dice roll. If it lands exactly on square 13, it slides back to square 5. The game ends when the piece reaches square 20 or beyond.

    Write turns_to_finish(rolls) that takes a list of dice results and returns how many turns the game took. If the list runs out before the piece finishes, return -1.

    turns_to_finish([6, 6, 6, 6])        ->  4    (6, 12, 18, 24)
    turns_to_finish([6, 6, 1, 6, 6, 6])  ->  6    (6, 12, 13 so back to 5, 11, 17, 23)

    Taking the rolls as a list keeps the game rules testable. In a simulation, the list would come from random.randint(1, 6).

    def turns_to_finish(rolls):
    # Move the piece, slide from 13 back to 5, stop at 20 or beyond
    pass

    Exam topics: 3.15 Random Values (AAP-3.E), 3.16 Simulations (AAP-3.F)

    Related Tutorials

    Was this tutorial helpful?