Random-number generation

Chez Scheme provides a built-in procedure random that is often helpful in modelling real-world phenomena that do not follow any obvious algorithms and are not predictable.

When the random procedure is given an exact positive integer as argument, it returns some non-negative integer less than the argument, but not always the same one. Over a long series of calls, you'll get back each non-negative integer less than the argument about equally often. So, for example, the call (random 20) always yields some integer in the range from 0 to 19, and over a long series of calls you can expect each of those values to be returned about one-twentieth of the time.

> (random 20)
4
> (random 20)
17
> (random 20)
16

When the argument to random is an inexact positive real (typically specified by a numeral containing a decimal point), random returns some non-negative real value less than the argument. Over a long series of identical calls, the values returned will be distributed approximately evenly throughout the interval from 0.0 (inclusive) to the value of the argument (exclusive).

> (random 1.5)
0.046003446339158316
> (random 1.5)
1.3329912409120568
> (random 1.5)
1.4584015323556465
> (random 1.5)
0.14671341559491913
> (random 1.5)
1.1500817949427606

A typical use of random is to simulate the rolling of an ordinary six-sided die. The roll-a-die procedure returns a random integer in the range from 1 to 6:

(define roll-a-die
  (lambda ()
    (+ 1 (random 6))))

Note that roll-a-die takes no arguments. To invoke it, just write its name between parentheses: (roll-a-die).

Another common application of random is to select an element at random from a non-empty list. The random-element procedure performs this operation on a given list:

(define random-element
  (lambda (ls)
    (list-ref ls (random (length ls)))))

In English: To choose a random element from a list, obtain a random non-negative integer less than the length of that list and select the element at that position in the list.

> (random-element '(a b c d e f g))
c
> (random-element '(a b c d e f g))
f
> (random-element '(a b c d e f g))
b
> (random-element '(111 112 114 118 126))
112
> (random-element '(only))
only

Exercise 1

Define a toss-a-coin procedure that takes no arguments and returns either the string "heads" or the string "tails", about equally often over a long series of calls.


Exercise 2

Define a procedure named roll-two-dice that takes no arguments, simulates the independent rolling of two dice, and returns the total of the numbers on the faces that turn up.


Exercise 3

Define a procedure named random-Boolean-list that takes one argument, a non-negative integer, and constructs and returns a list of the length specified by that argument. Each element of the list should be one of the Boolean values #t and #f, chosen independently, at random, and with equal probability. For instance, the call (random-Boolean-list 4) might return the value (#t #t #f #t).


Exercise 4

According to the Des Moines Register (September 10, 1997, page 1M), registered voters in Iowa have declared the following party affiliations:

Democratic Party    558801
Reform Party            81
Republican Party    583897
unaffiliated        583002
--------------------------
  total            1725781

Define a procedure named random-voter-affiliation that takes no arguments and returns the symbol Democrat 558801/1725781 of the time, the symbol Reform 81/1725781 of the time, the symbol Republican 583897/1725781 of the time, and the symbol mugwump 583002/1725781 of the time.


This document is available on the World Wide Web as

http://www.math.grin.edu/courses/Scheme/spring-1998/random-number-generation.html

created February 7, 1997
last revised June 21, 1998

John David Stone (stone@math.grin.edu)