Since random number generators are useful, and are used in many
assignments, we will highlight a few aspects of random number
generation, starting with the most basic generator:
(source file )
public class uniform_random {
// Basic Lehmer generator - constants
static final long m = 2147483647L;
static final long a = 48271L;
static final long q = 44488L;
static final long r = 3399L;
// "Global" variable - the seed, set to some
// arbitrary non-zero value.
static long r_seed = 12345678L;
// Basic Lehmer generator - uniform[0,1]
// For more information see Knuth, Vol. II.
public static double uniform ()
{
long hi = r_seed / q;
long lo = r_seed - q * hi;
long t = a * lo - r * hi;
if (t > 0)
r_seed = t;
else
r_seed = t + m;
return ( (double) r_seed / (double) m );
}
public static void main (String[] argv)
{
// Let's test the generator. The mean should be 0.5.
double sum = 0;
for (int i=1; i<=10000; i++)
sum += uniform ();
System.out.println ("Average of 10000 samples: " + sum/10000);
}
}
This generator is an example of the well-known Lehmer class of random number generators:
Consider the following modification to the above code: (source file )
public class uniform_random {
// Basic Lehmer generator - constants
static final long m = 2147483647L;
static final long a = 48271L;
static final long q = 44488L;
static final long r = 3399L;
// "Global" variable - the seed, set to some
// arbitrary non-zero value.
static long r_seed = 12345678L;
// Basic Lehmer generator - uniform[0,1]
// For more information see Knuth, Vol. II.
public static double uniform ()
{
long hi = r_seed / q;
long lo = r_seed - q * hi;
long t = a * lo - r * hi;
if (t > 0)
r_seed = t;
else
r_seed = t + m;
double returnValue = ( (double) r_seed / (double) m );
System.out.println ("r_seed=" + r_seed + " m=" + m + " returnValue=" + returnValue);
return returnValue;
}
public static void main (String[] argv)
{
// Print out 10 values.
for (int i=1; i<=10; i++)
uniform ();
}
}
Here's what gets printed out:
r_seed=1085252519 m=2147483647 returnValue=0.5053600852868334 r_seed=508259731 m=2147483647 returnValue=0.23667688073435653 r_seed=1352291773 m=2147483647 returnValue=0.6297099281240767 r_seed=1563240271 m=2147483647 returnValue=0.7279404773041329 r_seed=890733155 m=2147483647 returnValue=0.414779947798131 r_seed=1810028418 m=2147483647 returnValue=0.8428601635819581 r_seed=1509587083 m=2147483647 returnValue=0.7029562647002545 r_seed=862973489 m=2147483647 returnValue=0.4018533459873187 r_seed=1852986660 m=2147483647 returnValue=0.8628641538614706 r_seed=677683663 m=2147483647 returnValue=0.3155710470469534
Now, it's important to realize that the random numbers so produced have the property of being uniform:
Next, an obvious question is: what should the initial value of
r_seed be?
Answer:
If you execute the file once, you get the output:
r_seed=1085252519 m=2147483647 returnValue=0.5053600852868334
r_seed=508259731 m=2147483647 returnValue=0.23667688073435653
r_seed=1352291773 m=2147483647 returnValue=0.6297099281240767
r_seed=1563240271 m=2147483647 returnValue=0.7279404773041329
r_seed=890733155 m=2147483647 returnValue=0.414779947798131
r_seed=1810028418 m=2147483647 returnValue=0.8428601635819581
r_seed=1509587083 m=2147483647 returnValue=0.7029562647002545
r_seed=862973489 m=2147483647 returnValue=0.4018533459873187
r_seed=1852986660 m=2147483647 returnValue=0.8628641538614706
r_seed=677683663 m=2147483647 returnValue=0.3155710470469534
Now if you execute again, you get:
r_seed=1085252519 m=2147483647 returnValue=0.5053600852868334
r_seed=508259731 m=2147483647 returnValue=0.23667688073435653
r_seed=1352291773 m=2147483647 returnValue=0.6297099281240767
r_seed=1563240271 m=2147483647 returnValue=0.7279404773041329
r_seed=890733155 m=2147483647 returnValue=0.414779947798131
r_seed=1810028418 m=2147483647 returnValue=0.8428601635819581
r_seed=1509587083 m=2147483647 returnValue=0.7029562647002545
r_seed=862973489 m=2147483647 returnValue=0.4018533459873187
r_seed=1852986660 m=2147483647 returnValue=0.8628641538614706
r_seed=677683663 m=2147483647 returnValue=0.3155710470469534
It's the same output! So, how can we call this random?
Here's what's going on:
public class random_example {
static final long m = 2147483647L;
static final long a = 48271L;
static final long q = 44488L;
static final long r = 3399L;
static long r_seed = 12345678L;
public static double uniform ()
{
long hi = r_seed / q;
long lo = r_seed - q * hi;
long t = a * lo - r * hi;
if (t > 0)
r_seed = t;
else
r_seed = t + m;
return ( (double) r_seed / (double) m );
}
public static void main (String[] argv)
{
double[] A = new double [5];
int howManyArrays = 3;
for (int n=1; n<=howManyArrays; n++) {
// Generate random values;
for (int i=0; i<5; i++)
A[i] = uniform();
// Print out array.
System.out.print ("Array #" + n + " : ");
for (int i=0; i<5; i++)
System.out.print (" " + A[i]);
System.out.println ();
}
}
}
Thus, to perform estimation, we will need to run an experiment multiple times and take an average:
As an example, consider the following experiment:
public class random_example2 {
static final long m = 2147483647L;
static final long a = 48271L;
static final long q = 44488L;
static final long r = 3399L;
static long r_seed = 12345678L;
public static double uniform ()
{
long hi = r_seed / q;
long lo = r_seed - q * hi;
long t = a * lo - r * hi;
if (t > 0)
r_seed = t;
else
r_seed = t + m;
return ( (double) r_seed / (double) m );
}
public static void main (String[] argv)
{
double[] A = new double [5];
int numArrays = 10000;
int numOccurences = 0;
for (int n=1; n<=numArrays; n++) {
for (int i=0; i<5; i++)
A[i] = uniform();
// Check for property.
boolean property = true;
for (int i=1; i<5; i++) {
if (A[i] < A[i-1])
property = false;
}
// Count.
if (property)
numOccurences++;
}
// Now estimate probability.
double prob = (double) numOccurences / (double) numArrays;
System.out.println ("Probability estimate: " + prob);
}
}