Java tutorial
// $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(); } } } }