Update 1, 1/25/2011:21:53

Homework Three: How Random is Pseudorandom?

For this assignment, you will extend your PRNG class from Assignment Two so that it generates floating-point (double) numbers in the range 0 to 1.0 instead of integers in the range 0 to modulus-1. Also, you will provide evaluation methods that test the randomness quality of you pseudorandom number generator.

Objectives for this assignment

The goals for this assignment is to provide you with: more practice using Java and working with arrays, improved understanding of constructors and inheritance, broadened understanding of pseudo random number generators, and a more full-featured random number generator.

Problem requirements: Part I

Write a new class, UniformRandom, that extends your PRNG class from Assignment Two. First, provide at least a constructor that corresponds to the four argument version from your PRNG class; you are welcome to provide other constructors as you desire. However, someone using your new class should be able to create an instance of UniformRandom without any arguments.

Next, override your next() method. This new version of the method should return a Double instead of an Integer. As an aside, the observant coder will have already noticed that the next() method from the PRNG class was returning an instance of the Integer wrapper class. You might not have noticed this because Java kindly wraps an int in an Integer object when an Object is expected, and kindly unwraps the integer value from the Integer object when the simple value is needed. The same applies to all the other primitive types and their corresponding wrapper classes. However, because we want you to use the next() method of your super-class (PRNG) as override it for the UniformRandom class, you will be receiving an object, which must be cast in order to extract its value.

With that aside, you should override next() to return a double (Double) value between 0.0 (inclusive) and 1.0 (exclusive). You can accomplish the translation to the 0-1 range by dividing the newly generated number by your modulus. Because the number generated by your PRNG method from last week is the remainder of a division by the modulus, it will never be greater than or equal to the modulus. Therefore, when dividing by the modulus, the quotient will always be strictly less than 1.0.) If one repeatedly calls this new method, it should generate a sequence of pseudorandom numbers in the range [0.0 .. 1.0).

This should be the only method that you will need to override from your previous class. However, if you need or want to make changes to your version of PRNG (from which UniformRandom is inheriting), feel free to do so. Be sure to include a copy of your PRNG class with your submission whether you alter it or not.

Evaluating pseudorandom number generators

There are many applications of pseudorandom number generators. For some of those applications, the particular properties or characteristics of the distribution and sequence are of critical importance. There are a number of such characteristics, but for this assignment we will consider only two of them: the distribution of numbers and the pairwise relation between consecutive numbers in the sequence.

If we divide the range [0..1.0) into some number, say ten, of "bins" and assign each number in a large sample to the appropriate bin, we would hope that a good pseudorandom number generator would fill the ten bins roughly evenly. This test checks the distribution of numbers given ensuring each number in the range is as likely to be generated as the other numbers. This alone, however, is insufficient. The sequence of numbers 0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,.... perfectly distributes numbers into the ten bins but we would hardly call this a good pseudorandom sequence.

One additional check we can employ is to track the relationship between consecutive numbers. This test checks the sequence for regularities that would reflect non-randomness. If we keep track of the number of times 0 is followed by each of the ten digits (including 0), and do the same for 1, 2 and all the other numbers, we can identify evenly distributed but non-random sequences such as the one above.

Problem requirements: Part II

Once your new method is generating numbers in the appropriate range, we want to be able to run experiments that evaluate the distribution and sequence of resulting numbers. Write two additional methods, public double[] checkDistribution(int howManyBins, int testSize) and public double[][] checkSequence(int howManyBins, int testSize) that will perform tests on your pseudorandom number generator along the lines discussed above. Your checkDistribution method should return a one-dimensional array containing the counts of numbers that fell into the respective ranges or bins. Your checkSequence returns a two-dimensional array where a cell indexed by i and j contains the number of times that j followed i in the sequence. The parameters determine the number of bins to use and how many samples to generate.

Because the purpose of these methods is to evaluate the "random" quality of your generator, you should write your main driver method to consume three integer inputs for the multiplier, increment and modulus. Then you will be able to run tests with different values of these parameters and observe their impact on the distribution and sequence.

Your main method should run checkDistribution and checkSequence on a given number of bins, say ten, over a large sample of generated random numbers, say one million. If using ten bins, you would divide the range [0..1) into ten smaller ranges: [0.. 0.1), [0.1 .. 0.2), ... [0.9 .. 1.0). Finally, print out your results in a manner such as shown in the screen shot.

Sample output from UniformRandom.java

Run your experiment several times with different values for the multiplier, increment, and modulus. A set of good choices for these will yield approximately 10% of the total in each range. A generator with this equal-interval behavior is called uniformly distributed. Try to find a set of values that produce a better distribution than the values recommended in Assignment 2. (Note, the initial seed value is not too important in this regard as long as you have a large sample. So don't worry too much about experimenting with that value.)

Update 1: As always, you should fully document your program using javadoc directives. Similarly, you should generate the html files resulting from those comments and inspect them for completeness and correctness. Include these html files in your final submission.

Submission instructions:

Make sure that you create a folder named with your Westmont email name followed by "HW3". For example, someone with email address "cjones" would create a folder called "cjonesHW3". Make sure that inside that folder you have: java source files as well as html documentation files resulting from javadoc. Finally, either tar or zip the folder so that when we extract it, the folder "<emailname>HW3" will be created. Submit the packaged file for assignment 3 on Eureka.