* Compilation: javac StdRandom.java
* Execution: java StdRandom
*
* A library of static methods to generate random numbers from
* different distributions (bernouilli, uniform, gaussian,
* discrete, and exponential). Also includes a method for
* shuffling an array.
*
* % java StdRandom 5
* 90 26.36076 false 8.79269 0
* 13 18.02210 false 9.03992 1
* 58 56.41176 true 8.80501 0
* 29 16.68454 false 8.90827 0
* 85 86.24712 true 8.95228 0
*
*
* Remark
* ------
* - Uses Math.random() which generates a pseudorandom real number
* in [0, 1)
*
* - This library does not allow you to set the pseudorandom number
* seed. See java.util.Random.
*
* - See [url=http://www.honeylocust.com/RngPack/]RngPack: High-Quality Random Numbers for Java[/url] for an industrial
* strength random number generator in Java.
*
*************************************************************************/
/**
* <i>Standard random</i>. This class provides methods for generating
* random number from various distributions.
* <p>
* For additional documentation, see <a href="http://www.cs.princeton.edu/introcs/22library">Section 2.2</a> of
* <i>Introduction to Programming in Java: An Interdisciplinary Approach</i> by Robert Sedgewick and Kevin Wayne.
*/
public class StdRandom {
/**
* Return real number uniformly in [0, 1).
*/
public static double uniform() {
return Math.random();
}
/**
* Return real number uniformly in [a, b).
*/
public static double uniform(double a, double b) {
return a + Math.random() * (b-a);
}
/**
* Return an integer uniformly between 0 and N-1.
*/
public static int uniform(int N) {
return (int) (Math.random() * N);
}
/**
* Return a boolean, which is true with probability p, and false otherwise.
*/
public static boolean bernoulli(double p) {
return Math.random() < p;
}
/**
* Return a real number with a standard Gaussian distribution.
*/
public static double gaussian() {
// use the polar form of the Box-Muller transform
double r, x, y;
do {
x = uniform(-1.0, 1.0);
y = uniform(-1.0, 1.0);
r = x*x + y*y;
} while (r >= 1 || r == 0);
return x * Math.sqrt(-2 * Math.log(r) / r);
// Remark: y * Math.sqrt(-2 * Math.log(r) / r)
// is an independent random gaussian
}
/**
* Return a real number from a gaussian distribution with given mean and stddev
*/
public static double gaussian(double mean, double stddev) {
return mean + stddev * gaussian();
}
/**
* Return a number from a discrete distribution: i with probability a[i].
*/
public static int discrete(double[] a) {
// precondition: sum of array entries equals 1
double r = Math.random();
double sum = 0.0;
for (int i = 0; i < a.length; i++) {
sum = sum + a[i];
if (sum >= r) return i;
}
assert (false);
return -1;
}
/**
* Return a real number from an exponential distribution with rate lambda.
*/
public static double exp(double lambda) {
return -Math.log(1 - Math.random()) / lambda;
}
// swaps array elements i and j
private static void exch(String[] a, int i, int j) {
String swap = a[i];
a[i] = a[j];
a[j] = swap;
}
/**
* Rearrange the elements of an array in random order.
*/
public static void shuffle(Object[] a) {
int N = a.length;
for (int i = 0; i < N; i++) {
int r = i + uniform(N-i); // between i and N-1
Object temp = a[i];
a[i] = a[r];
a[r] = temp;
}
}
/**
* Rearrange the elements of a double array in random order.
*/
public static void shuffle(double[] a) {
int N = a.length;
for (int i = 0; i < N; i++) {
int r = i + uniform(N-i); // between i and N-1
double temp = a[i];
a[i] = a[r];
a[r] = temp;
}
}
/**
* Rearrange the elements of an int array in random order.
*/
public static void shuffle(int[] a) {
int N = a.length;
for (int i = 0; i < N; i++) {
int r = i + uniform(N-i); // between i and N-1
int temp = a[i];
a[i] = a[r];
a[r] = temp;
}
}
/**
* Unit test.
*/
public static void main(String[] args) {
int N = Integer.parseInt(args[0]);
double[] t = { .5, .3, .1, .1 };
for (int i = 0; i < N; i++) {
StdOut.printf(" %2d " , uniform(100));
StdOut.printf("%8.5f ", uniform(10.0, 99.0));
StdOut.printf("%5b " , bernoulli(.5));
StdOut.printf("%7.5f ", gaussian(9.0, .2));
StdOut.printf("%2d " , discrete(t));
StdOut.println();
}
}
}