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 17sets the modulo constant to 101 and the multiplier to 17, but leaves the additive constant and the initial seed at their default values.
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.
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.
.
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 :