Skip to content

Instantly share code, notes, and snippets.

@hjhjw1991
Created January 5, 2016 06:37
Show Gist options
  • Save hjhjw1991/1b679d733c24ebb41604 to your computer and use it in GitHub Desktop.
Save hjhjw1991/1b679d733c24ebb41604 to your computer and use it in GitHub Desktop.
JavaUtils
import java.util.Random;
/**
* 此类提供一系列产生随机数的方法,以满足不同用例需要
* from Internet
* @author crazymonkey
*/
public final class NumberRandom {
// 随机数对象
private static Random random;
// 用于产生随机数的种子
private static long seed;
// 静态初始化区域
static {
// 产生随机数种子
seed = System.currentTimeMillis();
random = new Random(seed);
}
private NumberRandom() {
}
/***********************************************************
* 产生基本的随机数
***********************************************************/
/**
* 设置此类实例的伪随机种子生成器
*/
public static void setSeed(long s) {
seed = s;
random = new Random(seed);
}
/**
* 获取此类实例提供的伪随机种子生成器
*/
public static long getSeed() {
return seed;
}
/**
* 返回一个随机的范围在[0,1)之间的double类型的数
*/
public static double uniform() {
return random.nextDouble();
}
/**
* 返回一个随机的范围在[0,n)之间的int类型的数
*/
public static int uniform(int n) {
return random.nextInt(n);
}
/**
* 返回一个范围在 [0, 1)的实数
*/
public static double random() {
return uniform();
}
/**
* 返回一个范围在 [a, b)的int类型值
*/
public static int uniform(int a, int b) {
return a + uniform(b - a);
}
/**
* 返回一个范围在 [a, b)的实数
*/
public static double uniform(double a, double b) {
return a + uniform() * (b - a);
}
/**
* 返回一个随机boolean值,该p表示此布尔值为真的概率
*
* @param p
* 0~1 之间的double值,表示产生boolean真值的可能性
*/
public static boolean bernoulli(double p) {
return uniform() < p;
}
/**
* 返回一个随机boolean值,此布尔值为真的概率为0.5
*/
public static boolean bernoulli() {
return bernoulli(0.5);
}
/***********************************************************
* 产生满足特定概率分布的实数
***********************************************************/
/**
* 返回一个满足标准正态分布的实数
*/
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);
}
/**
* 返回一个满足平均值为mean,标准差为stddev的正态分布的实数
*
* @param mean
* 正态分布的平均值
* @param stddev
* 正太分布的标准差
*/
public static double gaussian(double mean, double stddev) {
return mean + stddev * gaussian();
}
/**
* 返回一个满足几何分布的整型值 平均值为1/p
*/
public static int geometric(double p) {
// knuth
return (int) Math.ceil(Math.log(uniform()) / Math.log(1.0 - p));
}
/**
* 根据指定的参数返回一个满足泊松分布的实数
*/
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;
}
/**
* 根据指定的参数按返回一个满足帕雷托分布的实数
*/
public static double pareto(double alpha) {
return Math.pow(1 - uniform(), -1.0 / alpha) - 1.0;
}
/**
* 返回一个满足柯西分布的实数
*/
public static double cauchy() {
return Math.tan(Math.PI * (uniform() - 0.5));
}
/**
* 返回一个满足离散分布的int类型的数
*
* @param a
* 算法产生随机数过程中需要使用此数组的数据,a[i]代表i出现的概率 前提条件 a[i] 非负切和接近 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("数组元素" + i + "为负数:" + a[i]);
sum = sum + a[i];
}
if (sum > 1.0 + epsilon || sum < 1.0 - epsilon)
throw new IllegalArgumentException("数组各个元素之和为:" + 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;
}
}
}
/**
* 返回一个满足指数分布的实数,该指数分布比率为lambda
*/
public static double exp(double lambda) {
return -Math.log(1 - uniform()) / lambda;
}
/***********************************************************
* 数组操作
***********************************************************/
/**
* 随机打乱指定的object型数组
*
* @param a
* 待打乱的object型数组
*/
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;
}
}
/**
* 随机打乱指定的double型数组
*
* @param a
* 待打乱的double型数组
*/
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;
}
}
/**
* 随机打乱指定的int型数组
*
* @param a
* 待打乱的int型数组
*/
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;
}
}
/**
* 随机打乱指定object类型数组中指定范围的数据
*
* @param a
* 指定的数组
* @param lo
* 起始位置
* @param hi
* 结束位置
*/
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;
}
}
/**
* 随机打乱指定double类型数组中指定范围的数据
*
* @param a
* 指定的数组
* @param lo
* 起始位置
* @param hi
* 结束位置
*/
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;
}
}
/**
* 随机打乱指定int类型数组中指定范围的数据
*
* @param a
* 指定的数组
* @param lo
* 起始位置
* @param hi
* 结束位置
*/
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;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment