A GaussianHat is a random number generator that will give you numbers based on a population mean and standard deviation.
// $Id: GaussianHat.java 12 2009-11-09 22:58:47Z gabe.johnson $
//package org.six11.util.data;
import java.util.Random;
/**
* A GaussianHat is a random number generator that will give you numbers based
* on a population mean and standard deviation. You can ask it for integers or
* probabilities. You may also specify a floor and ceiling (so in that case it's
* not truely Gaussian).
*/
public class GaussianHat {
// this is necessary because if you create a few GaussianHats
// during the same millisecond and then use them in the exact
// manner, they will yield the same 'random' numbers if you ask
// for the same kinds of random numbers in the same order, which
// is absolutely no good. So we'll create a single Random that
// will then generate better Randoms from it.
static Random staticRand;
static {
staticRand = new Random(System.currentTimeMillis());
}
double mean;
double sd;
Random rand;
double floor;
double ceiling;
/**
* Creates a copy of the input GaussianHat.
*/
public GaussianHat(GaussianHat other) {
this(other.mean, other.sd, other.floor, other.ceiling);
}
public GaussianHat(double mean, double sd, double floor, double ceiling) {
this.mean = mean;
this.sd = sd;
this.floor = floor;
this.ceiling = ceiling;
this.rand = new Random(staticRand.nextLong());
}
public GaussianHat(double mean, double sd) {
this(mean, sd, 0, Double.MAX_VALUE);
}
public GaussianHat(int mean, double sd) {
this((double) mean, sd);
}
public GaussianHat(int mean, int sd) {
this((double) mean, (double) sd);
}
public GaussianHat(int mean, int sd, int floor, int ceiling) {
this((double) mean, (double) sd, (double) floor, (double) ceiling);
}
public GaussianHat(double mean) {
this(mean, 1.0);
}
public void setMean(double mean) {
this.mean = mean;
}
public void setStdDev(double sd) {
this.sd = sd;
}
public int getInt() {
// simply return getDouble() as an int.
return (int) getDouble();
}
public double getDouble() {
// based on the mean and standard deviation, pick a number from a normal
// distribution, cast it to an integer
double d = (rand.nextGaussian() * sd) + mean;
if (d < floor)
d = floor;
if (d > ceiling)
d = ceiling;
return d;
}
public double getUniformDouble() {
double d = rand.nextDouble();
d = floor + (d * (ceiling - floor));
return d;
}
public boolean getYesNo() {
// get a random number from uniform distribution 0..1 and return true if
// that number is less than or equal to the provided 'chance' parameter
return (rand.nextDouble() <= mean);
}
public String toString() {
return mean + " (" + sd + ")";
}
public static void main(String[] args) {
// I have convinced myself that my randomness is OK using JMP
GaussianHat[] intHats = new GaussianHat[] { new GaussianHat(10, 2),
new GaussianHat(10, 4), new GaussianHat(20, 2),
new GaussianHat(20, 4) };
GaussianHat[] chanceHats = new GaussianHat[] {
new GaussianHat(0.60, 0.05), new GaussianHat(0.60, 0.15),
new GaussianHat(0.30, 0.05), new GaussianHat(0.30, 0.15) };
for (int trial = 1; trial <= 100; trial++) {
for (int i = 0; i < intHats.length; i++) {
System.out.print(intHats[i].getInt() + "\t");
if (i == (intHats.length - 1))
System.out.println();
}
}
for (int trial = 1; trial <= 100; trial++) {
for (int i = 0; i < chanceHats.length; i++) {
System.out.print(chanceHats[i].getYesNo() + "\t");
if (i == (chanceHats.length - 1))
System.out.println();
}
}
}
}
Related examples in the same category