StdRandom提供一系列的靜態(tài)方法用于產(chǎn)生滿足多種需求的隨機(jī)數(shù),具體代碼如下:
package crazymonkey.math;
import java.util.Random;
/**
* 此類提供一系列產(chǎn)生隨機(jī)數(shù)的方法,以滿足不同用例需要
* @author crazyMonkey
*/
public final class StdRandom {
//隨機(jī)數(shù)對(duì)象
private static Random random;
//用于產(chǎn)生隨機(jī)數(shù)的種子
private static long seed;
// 靜態(tài)初始化區(qū)域
static {
//產(chǎn)生隨機(jī)數(shù)種子
seed = System.currentTimeMillis();
random = new Random(seed);
}
private StdRandom() { }
/***********************************************************
* 產(chǎn)生基本的隨機(jī)數(shù)
***********************************************************/
/**
* 獲取此類實(shí)例的偽隨機(jī)種子生成器
*/
public static void setSeed(long s) {
seed = s;
random = new Random(seed);
}
/**
* 獲取此類實(shí)例提供的偽隨機(jī)種子生成器
*/
public static long getSeed() {
return seed;
}
/**
* 返回一個(gè)隨機(jī)的范圍在[0,1)之間的double類型的數(shù)
*/
public static double uniform() {
return random.nextDouble();
}
/**
* 返回一個(gè)隨機(jī)的范圍在[0,N)之間的int類型的數(shù)
*/
public static int uniform(int N) {
return random.nextInt(N);
}
/**
* 返回一個(gè)范圍在 [0, 1)的實(shí)數(shù)
*/
public static double random() {
return uniform();
}
/**
* 返回一個(gè)范圍在 [a, b)的int類型值
*/
public static int uniform(int a, int b) {
return a + uniform(b - a);
}
/**
* 返回一個(gè)范圍在 [a, b)的實(shí)數(shù)
*/
public static double uniform(double a, double b) {
return a + uniform() * (b-a);
}
/**
* 返回一個(gè)隨機(jī)boolean值,該p表示此布爾值為真的概率
* @param p 0~1 之間的double值,表示產(chǎn)生boolean真值的可能性
*/
public static boolean bernoulli(double p) {
return uniform() < p;
}
/**
* 返回一個(gè)隨機(jī)boolean值,此布爾值為真的概率為0.5
*/
public static boolean bernoulli() {
return bernoulli(0.5);
}
/***********************************************************
* 產(chǎn)生滿足特定概率分布的實(shí)數(shù)
***********************************************************/
/**
* 返回一個(gè)滿足標(biāo)準(zhǔn)正態(tài)分布的實(shí)數(shù)
*/
public static double gaussian() {
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);
}
/**
* 返回一個(gè)滿足平均值為mean,標(biāo)準(zhǔn)差為stddev的正態(tài)分布的實(shí)數(shù)
* @param mean 正態(tài)分布的平均值
* @param stddev 正太分布的標(biāo)準(zhǔn)差
*/
public static double gaussian(double mean, double stddev) {
return mean + stddev * gaussian();
}
/**
* 返回一個(gè)滿足幾何分布的整型值 平均值為1/p
*/
public static int geometric(double p) {
// Knuth
return (int) Math.ceil(Math.log(uniform()) / Math.log(1.0 - p));
}
/**
* 根據(jù)指定的參數(shù)返回一個(gè)滿足泊松分布的實(shí)數(shù)
*/
public static int poisson(double lambda) {
// 使用 Knuth 的算法
// 參見
int k = 0;
double p = 1.0;
double L = Math.exp(-lambda);
do {
k++;
p *= uniform();
} while (p >= L);
return k-1;
}
/**
* 根據(jù)指定的參數(shù)按返回一個(gè)滿足帕雷托分布的實(shí)數(shù)
*/
public static double pareto(double alpha) {
return Math.pow(1 - uniform(), -1.0/alpha) - 1.0;
}
/**
* 返回一個(gè)滿足柯西分布的實(shí)數(shù)
*/
public static double cauchy() {
return Math.tan(Math.PI * (uniform() - 0.5));
}
/**
* 返回一個(gè)滿足離散分布的int類型的數(shù)
* @param a 算法產(chǎn)生隨機(jī)數(shù)過程中需要使用此數(shù)組的數(shù)據(jù),a[i]代表i出現(xiàn)的概率
* 前提條件 a[i] 非負(fù)切和接近 1.0
*/
public static int discrete(double[] a) {
double EPSILON = 1E-14;
double sum = 0.0;
for (int i = 0; i < a.length; i++) {
if (a[i] < 0.0) throw new IllegalArgumentException("數(shù)組元素 " + i + " 為負(fù)數(shù): " + a[i]);
sum = sum + a[i];
}
if (sum > 1.0 + EPSILON || sum < 1.0 - EPSILON)
throw new IllegalArgumentException("數(shù)組各個(gè)元素之和為: " + sum);
while (true) {
double r = uniform();
sum = 0.0;
for (int i = 0; i < a.length; i++) {
sum = sum + a[i];
if (sum > r) return i;
}
}
}
/**
* 返回一個(gè)滿足指數(shù)分布的實(shí)數(shù),該指數(shù)分布比率為lambda
*/
public static double exp(double lambda) {
return -Math.log(1 - uniform()) / lambda;
}
/***********************************************************
* 數(shù)組操作
***********************************************************/
/**
* 隨機(jī)打亂指定的Object型數(shù)組
* @param a 待打亂的Object型數(shù)組
*/
public static void shuffle(Object[] a) {
int N = a.length;
for (int i = 0; i < N; i++) {
int r = i + uniform(N-i);
Object temp = a[i];
a[i] = a[r];
a[r] = temp;
}
}
/**
* 隨機(jī)打亂指定的double型數(shù)組
* @param a 待打亂的double型數(shù)組
*/
public static void shuffle(double[] a) {
int N = a.length;
for (int i = 0; i < N; i++) {
int r = i + uniform(N-i);
double temp = a[i];
a[i] = a[r];
a[r] = temp;
}
}
/**
* 隨機(jī)打亂指定的int型數(shù)組
* @param a 待打亂的int型數(shù)組
*/
public static void shuffle(int[] a) {
int N = a.length;
for (int i = 0; i < N; i++) {
int r = i + uniform(N-i);
int temp = a[i];
a[i] = a[r];
a[r] = temp;
}
}
/**
* 隨機(jī)打亂指定Object類型數(shù)組中指定范圍的數(shù)據(jù)
*
* @param a 指定的數(shù)組
* @param lo 起始位置
* @param hi 結(jié)束位置
*/
public static void shuffle(Object[] a, int lo, int hi) {
if (lo < 0 || lo > hi || hi >= a.length) {
throw new IndexOutOfBoundsException("不合法的邊界");
}
for (int i = lo; i <= hi; i++) {
int r = i + uniform(hi-i+1);
Object temp = a[i];
a[i] = a[r];
a[r] = temp;
}
}
/**
* 隨機(jī)打亂指定double類型數(shù)組中指定范圍的數(shù)據(jù)
*
* @param a 指定的數(shù)組
* @param lo 起始位置
* @param hi 結(jié)束位置
*/
public static void shuffle(double[] a, int lo, int hi) {
if (lo < 0 || lo > hi || hi >= a.length) {
throw new IndexOutOfBoundsException("不合法的邊界");
}
for (int i = lo; i <= hi; i++) {
int r = i + uniform(hi-i+1);
double temp = a[i];
a[i] = a[r];
a[r] = temp;
}
}
/**
* 隨機(jī)打亂指定int類型數(shù)組中指定范圍的數(shù)據(jù)
*
* @param a 指定的數(shù)組
* @param lo 起始位置
* @param hi 結(jié)束位置
*/
public static void shuffle(int[] a, int lo, int hi) {
if (lo < 0 || lo > hi || hi >= a.length) {
throw new IndexOutOfBoundsException("不合法的邊界");
}
for (int i = lo; i <= hi; i++) {
int r = i + uniform(hi-i+1);
int temp = a[i];
a[i] = a[r];
a[r] = temp;
}
}
}
更多信息請(qǐng)查看IT技術(shù)專欄