随机数
证明,等概率随机
@Test
public void equalProbabilityRandom() {
int testTimes = 10000000;
int count = 0;
for (int i = 0; i < testTimes; i++) {
double random = Math.random();
if (random < 0.5) {
count++;
}
}
System.out.println("随机概率为:" + ((double)count / (double) testTimes)); // 0.5000338
}
上述代码,出现[0, 0.5)
范围的数的概率为0.5,同理,出现 [0, 0.1)
的概率为 0.1,.... 故出现[0, x)
(0 <= x < 1
)的概率为x。
将 [0, x) 出现的概率由 x 变为 x^2
@Test
public void equalProbabilityRandom() {
int testTimes = 10000000;
int count = 0;
for (int i = 0; i < testTimes; i++) {
double random = Math.max(Math.random(), Math.random());
if (random < 0.5) {
count++;
}
}
System.out.println("随机概率为:" + ((double)count / (double) testTimes)); // 0.2501026
}
Math.max(Math.random(), Math.random())
,两次都必须出现 [0, x)
范围的数才符合范围。使用 max
取较大的数,判断较大的数是否为符合范围的,如果较大的符合,较小的数更符合,所以使用max
而不是 min
。
面试题
从15随机到17随机
有一个函数 f()
,可以返回 1 ~ 5等概率的随机整数;要求使用 f()
函数,生成一个新的随机函数g()
,可以返回 1 ~ 7 的等概率的随机整数。
@Test
public void m1to5and1to7() {
int testTimes = 1000000;
int[] counts = new int[8];
for (int i = 0; i < testTimes; i++) {
int num = g();
counts[num]++;
}
// 打印每个的次数
for (int i = 0; i < counts.length; i++) {
System.out.println("数字" + i + "出现的次数为" + counts[i]);
}
}
// 返回 1 ~ 5等概率的随机整数
public int f() {
return (int) (Math.random() * 5 + 1);
}
// 根据 f() 构造一个等概率的 0 1 发生器
public int f1() {
// 1, 2, 3, 4, 5
// 0, 0, 重来, 1, 1
while (true) {
int num = f();
if (num < 3) {
return 0;
}
if (num > 3) {
return 1;
}
}
}
// 要想得到 1 ~ 7 范围的数,可以先构造 0 ~ 7 的等概率随机函数
// 使用 0 1 发生器构建二进制数,随机生成 0 ~ 7 内的数字
// 000 ~ 111
public int f2() {
return (f1() << 2) + (f1() << 1) + f1();
}
// 使用f2() 剔除 7,或者剔除 0,完成 1~7的随机
public int g() {
int num;
do {
num = f2();
} while (num == 0);
return num;
}
**扩展:**从a~b
随机到c~d
随机的实现。
从01不等概率随机到01等概率随机
给定一个函数x()
,已知x会以固定概率返回0和1,但是0和1是不等概率随机的。比如0的概率为0.78,1的概率为0.22;如果通过不等概率随机变为等概率随机返回0和1的函数y()
?
@Test
public void notEqual0and1() {
int testTimes = 1000000;
int[] counts = new int[2];
for (int i = 0; i < testTimes; i++) {
counts[y()]++;
}
for (int i = 0; i < counts.length; i++) {
System.out.println("数字" + i + "出现的概率为" + counts[i]);
}
}
public int x() {
return Math.random() < 0.86 ? 0: 1;
}
// 将x()随机两次
// 出现 01 的概率是与出现 10的概率相同的
// 故代码如下:
public int y() {
int num;
do {
num = x();
} while (num == x());
return num;
}
最后更新于
这有帮助吗?