Computer Science 2611
Summer 2000
Laboratory Assignment 6

Handed out: 7/3/00

Pseudo-random number generators

Sometimes it is useful for a computer to produce a random number. Most computers do not have the ability to produce a genuinely random number, but there are methods for creating numbers that are apparently random.

The idea is to produce a function called next. You start with an integer called the seed. Define r0 to be the seed. Then define

r1 = next(r0)
r2 = next(r1)
r3 = next(r2)
etc. For example, suppose that function next is defined so that next(n) = (17*n + 1) mod 23. Choose the seed to be 2. Then the sequence of numbers is
r0 = 2
r1 = next (2) = 12
r2 = next (12) = 21
r3 = next (21) = 13
So the sequence of "apparently" random numbers starts 12, 21, 13, ... (We won't use the seed as one of the pseudo-random numbers.) What is the next number in the sequence? Notice that the numbers in this sequence will never be larger than 22. Also, the sequence repeats after a while. It goes 12, 21, 13, 15, 3, 6, 11, 4, 0, 1, 18, 8, 22, 7, 5, 17, 14, 9, 16, 20, 19, 2, 12, 21, 13, 15, ...

Different pseudo-random number generators use different functions next . One kind of functions uses next(n) = (a*n + b) mod c, where a and c are prime numbers, a < c and b < c. Generally, you choose c to be fairly large, so that it takes a long time before the sequence starts to repeat.

Pseudo-random number generating objects

An object R that acts as a pseudo-random number generator has two public methods:

SetSeed
R.SetSeed(n) tells object R to set its current seed to n. R must remember n as its current value.

nextRandom
R.nextRandom() returns the next random number in the sequence. It must update the current value that R is holding, so that several calls to R.nextRandom() produce different numbers. It just replaces the current value of R by the next value in the sequence, and returns that new value.

Suppose that a class Random is created for pseudo-random number generator objects. Then here is a function that produces the sum of n pseudo-random numbers. It is only given as an example of using a pseudo-random number generator; this function will not be part of your assignment. It sets the initial seed to 35.

   int randomSum(int n)
   {
     int k, sum;
     Random R;
     R.SetSeed(35);
     k = 0;
     sum = 0;
     while(k < n) {
       sum = sum + R.nextRandom();
       k++;
     }
     return sum;
   }
Notice that the seed is only set once, and then several pseudo-random numbers are asked for.

Here is another example function. It performs a "coin toss", producing either true or false. It does not want to create a new random number generator for each coin toss, so it has a random number generator as a parameter. Notice that, since the random number generator is an object, it is passed by reference.

   bool cointoss(Random& R)
   {
     return R.nextRandom() % 2;
   }

The assignment, part 1

Write a class of objects that are pseudo-random number generators. (This is the class Random of the example above.) Use a next function next(n) = (a*n + b) mod c, choosing numbers a, b and c to be fairly large prime numbers. Keep them less than 32,000, or there will be problems with arithmetic overflow. Be sure that a, b and c are different prime numbers, or your pseudo-random number generator will produce poor results.

Each object should hold a value that is its current value . Make the variable(s) in the object private. Each object should have a function SetSeed that sets the current value to a particular value, and a function nextRandom that changes the current value to the next value in the pseudo-random sequence, and returns that next value. Each call to nextRandom should produce an different number.

Write a main program to test the pseudo-random number generator. Just have it print the first 20 numbers generated, after setting the seed. Do the numbers look reasonable? Do not move on to part 2 until you have a working pseudo-random number generator class.

Hints

Draw a picture of a pseudo-random number generator object. What variable(s) does it need? What public methods does it have? Does it have any private methods?

Note that the constants a, b and c are not variables, they are constants. They are only used in one place, the next function. So build them into the next function, not into the object. You can declare a constant using the keyword const. For example, to declare constant b (of type long) to be 917, use

    const long b = 917;

To test whether a number is prime, you can just run a program. For your benefit, here is a function that will tell whether a number is prime. It will help you to choose reasonable values for a, b and c.

   bool isPrime(long n)
   {
     if(n < 2) return 0;

     long k = 2;
     while(k*k <= n) {
       if(n % k == 0) return 0;
       k++;
     }
     return 1;
   }

Assignment part 2: Using the random number generator

Two numbers are relatively prime if their greatest common divisor is 1. Suppose you choose two integers between 1 and N at random. What is the probability that they are relatively prime? As N gets large, that probability approaches 6/pi2, where pi = 3.14159265...

So one way to estimate pi is to select pairs of numbers at random from a large range, and to keep track of the fraction of the pairs that consist of two relatively prime numbers. The result should be close to 6/pi2. How can you estimate pi from your result?

Write a main program that reads two integers K and S. It should create a random number generator object, set the object's seed to S, and then get K pairs of random numbers. (That is a total of 2K random numbers, since you need two random numbers for each test.) It should then print an estimate of pi based on the number of pairs that were relatively prime. Show the estimate to five decimal places.

Test your program. Be careful with your arithmetic. Remember that the quotient of two integers is always forced to be an integer. If your answer is consistently 3.00000 or 3.16228 or 3.31662 there is something wrong with your program. 3.00000 is the square root of 9, 3.16228 is about the square root of 10, and 3.31662 is about the square root of 11. This indicates that you are using integer arithmetic where you need to use real arithmetic.

What to turn in

Turn in a printout of your solution to the second part. Be sure that it is well-commented and well-indented.