《算法导论》P117课后题5.1-2
Describe an implementation of the procedure Random(a, b) that only makes calls to Random(0,1). What is the expected running time of your procedure, as a function of a and b? The probability of the result of Random(a,b) should be pure uniformly distributed, as Random(0,1)
该问题的讨论区:http://stackoverflow.com/questions/8692818/how-to-implement-randoma-b-with-only-random0-1
该问题关键点是Random(a, b)生成的随机数在[a, b]中均匀分布,讨论区有两类典型错误。
第一类错误:
for i = 1 to b-a
r = a + Random(0,1)
return r
第二类错误:
r = a
for i = 1 to b - a //including b-a
r += Random(0,1)
return r
正确方法:
1) Find the smallest number, p
, such that 2^p > b-a
.
2) Perform the following algorithm:
r=0
for i = 1 to p
r = 2*r + Random(0,1)
3) If r
is greater than b-a
, go to step 2.
4) Your result is r+a
So let's try Random(1,3).
So b-a
is 2.
2^1 = 2
, so p
will have to be 2 so that 2^p
is greater than 2.
So we'll loop two times. Let's try all possible outputs:
00 -> r=0, 0 is not > 2, so we output 0+1 or 1.
01 -> r=1, 1 is not > 2, so we output 1+1 or 2.
10 -> r=2, 2 is not > 2, so we output 2+1 or 3.
11 -> r=3, 3 is > 2, so we repeat.
在此我用java测试如下:
/**
* 创建时间:2014年8月10日 下午2:48:08 项目名称:Test
*
* @author Cao Yanfeng
* @since JDK 1.6.0_21 类说明:
*/
public class RandomNumbersTest {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
System.out.println(getRandomNumber(1, 3));
}
/*
* new Random().nextInt(2)用来模拟Random(0,1),注意new
* Random().nextInt(2)表示生成≥0且<2的数,即生成0或1
*/
public static int getRandomNumber(int a, int b) {
int diff = b - a;
int p = getP(diff);
int result = 0;
for (int i = 1; i <= p; i++) {
int random = new Random().nextInt(2);
result = 2 * result + random;
/* 如果r大于b-a,重复第2)步 */
if (result > diff) {
result = 0;
i = 1;
}
}
return result + a;
}
/* 获得最小的p,使得2^p>b-a */
public static int getP(int diff) {
for (int i = (int) Math.ceil(Math.log(diff) / Math.log(2));; i++) {
if ((Math.pow(2, i)) > diff) {
return i;
}
}
}
}