Random Integer Generator

先占坑。以后再修改

昨天遇到一道题, Given int Rand(1) =  0或者 1- uniformly distributed,   write a function to implement Rand(29) - uniformly distributed。

由于本科时概率没学好,挂了。回来网上一查资料发现有类似的题目 -  Given Rand(5) = {1, 2, 3, 4, 5}, 求Rand(7)。

求Rand7的代码是

public static int random7() {
       int val = (random5() - 1) * 5 + (random5() - 1);  
       return val < 21 ? val % 7 + 1 : random7();
}

 

思路其实是把 1 - 5的数字映射到 1-7的范围,只要是uniformly distributed就行, 我们可以不在乎这 1 - 7的概率是 4%, 2 % , 还是 1%, 只要他们相等, 多余的部分我们再舍弃掉。比如计算范围是  1 - 10

  • 我们可以取 1 ,2, 3 ,4 ,5 ,6 ,7,  舍弃 8 - 10 (舍弃的方法是再call一次random函数,程序有可能死循环,但从概率上来看死循环几率极小)
  • 也可以取 4, 5, 6, 7, 8, 9, 10,舍弃 1 - 3,  但计算答案的时候    return val - 3

以上代码是一个解,我们还可以有其他的解。 比如以下,

 public static int random7() {
       int val = (random5() - 1) + (random5() - 1) * 5 + (random5() - 1) * 25;  
       return val < 119 ? val % 7 + 1 : random7();
}

原理就是,只要把random5()得到的数字均匀映射到一串大于7的连续数字里。

 

所以回到这个题目,Given rand(1)实现 rand(29),其中 rand1() =  0 或者 1,每次只有两个数,所以我们可以使用以下代码来映射到0 - 31, 再舍弃30 和31就可以了:

public static int rand29() {
       int val = rand1() + rand1() * 2 + rand1() * 4 + rand1() * 8 + rand1() * 16;    
       return val < 29 ? val: rand29();
}

 

2/25/2016

今天又看到有一个公式,假如给定m 和 n以及一个rand(1),那么求一个在m到n中间的数,可以用 rand(1) * (n - m) + n。这里题目不要求uniform distribution的话好像也可以这么做。

 

Reference:

http://www.growingwiththeweb.com/2014/03/given-random5-implement-random7.html

http://www.careercup.com/question?id=12426697

posted @ 2015-09-19 22:22  YRB  阅读(1667)  评论(0编辑  收藏  举报