【算法导论学习-009】仅使用Random(0,1)实现Random(a,b)

《算法导论》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;
			}
		}
	}

}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值