Random Numbers

Chapter: Random Numbers

Let's begin by looking at what, for a long time, served as the basis for "random" number generators for programmers. Basically it's the application of a formula to generate a new number from an old number -- over and over again, hoping that the sequence thus produced is unpredictable and uniformly distributed.

pseudorandomexpt.c contains very simple code to generate new seeds by applying a linear transformation and taking the result modulo m. It has been set up so that you can try different values of

For example running it as

pseudorandomexpt 101 17
sets the modulo constant to 101 and the multiplier to 17, but leaves the additive constant and the initial seed at their default values.


Exercise 10

With m set to 100, see if you can find values for a and r so that the resulting sequence has a period of 50. In other words, so that only half of the possible "random" numbers can occur after some point.

If you finish early, do a google search and see what you can find out about pseudo-random number generators. The next program you look at will be a little bit more sophisticated than the one you just played with (but not much).

Here is the code for pseudorandom.c. There's a similar program in the lab1 directory, but it doesn't have a main() method:

#include < stdio.h >
/* close up those angle brackets if you cut and paste! */
const long MM = 2147483647;  /* luckily, this is a Mersenne prime */
const long AA = 48271;
const long QQ = 44488;
const long RR = 3399;

long seed = 4071776L;  
/* This is an initial seed.
   Change it to anything you like to get a different sequence of
   pseudo-random numbers */

void set_seed(long new_seed) {
   seed = new_seed;
}

double prandom ()
/* A pseudorandom number generator due to Donald Knuth
  The Art of Computer Programming Volume 2 Semi-numerical Algorithms
  It uses a modulo technique to generate a fairly unpredictable and
  well-distributed sequence of seeds.  
  It returns a double formed by dividing the seed by MAXINT
*/
{
  long new_seed;
  new_seed = AA * (seed % QQ) - RR * (seed / QQ);
  if (new_seed > 0)
    seed = new_seed;
  else
    seed = new_seed + MM;
  return ( (double) seed / (double) MM );
}


double prandom_range (double lo, double hi)
/* Scale the result so it lies between lo and hi */ 
{
  if (hi > lo)
    return ( lo + (hi-lo) * prandom() );
  else { 
    printf ("ERROR: in prandom.prandom_range(): lo=%lf hi=%lf\n",lo,hi); 
    return 0;
  }
}
main(argc, argv) 
     int argc;
     char *argv[];
{
/* If the optional argument is on the commandline use it to reset the seed */
  if (argc > 1) set_seed(atoi(argv[1]));  
  int top = 100;                       /* default is ints from 0 - 99 */
  if (argc > 2) top = atoi(argv[2]);   /* but can be adjusted by second arg */
  int i;
  char continu = 'g';
  while (continu != 'q') {
    for (i = 0; i < 10; i++) {
      printf("%d ",  (int) prandom_range(0.0,top*1.0));
    }
    printf("\n");
    printf("Hit q to quit, ENTER to continue > ");
    continu = getchar();
  }
  getchar(); /* eat the CR/LF */
}

If you compile this via gcc -o pseudorandom pseudorandom.c and run it by simply typing pseudorandom you will get a sequence of pseudo-random numbers in the range 0-99. It will always be exactly the same sequence because the initial seed is fixed. By using argc and argv and atoi() you can select a new intial seed for each run. Typing pseudorandom 19071961 you will get a different sequence.

Q. 7
What is the point of this?


See if you can figure out what the second commandline argument does. Discuss!

One last exercise. A good idea is to modify the above code.


Exercise 11

Write a program to roll a pair of dice. Dice are cubical objects with six faces. Each face bears a representation of one of the numbers 1 through 6. Usually, the representation of n consists of n dots in a fairly symmetric pattern.

.

Just as the given program prompts for "Hit q to quit, ENTER to continue > " so should yours. But each time there should be an output line consisting of two numbers, each between 1 and 6. Rather like this:

: roll
4 3
Hit q to quit, ENTER to continue:
4 7
Hit q to quit, ENTER to continue:
3 3
Hit q to quit, ENTER to continue:q
:



rhyspj@gwu.edu