已知一个函数rand7()能够生成1-7的随机数,请给出一个函数rand10(),该函数能够生成1-10的随机数。
2012-07-16 21:12
295 查看
题目:
已知一个函数rand7()能够生成1-7的随机数,请给出一个函数,该函数能够生成1-10的随机数。
思路:
假如已知一个函数能够生成1-49的随机数,那么如何以此生成1-10的随机数呢?
解法:
该解法基于一种叫做拒绝采样的方法。主要思想是只要产生一个目标范围内的随机数,则直接返回。如果产生的随机数不在目标范围内,则丢弃该值,重新取样。由于目标范围内的数字被选中的概率相等,这样一个均匀的分布生成了。
显然rand7至少需要执行2次,否则产生不了1-10的数字。通过运行rand7两次,可以生成1-49的整数,
由于49不是10的倍数,所以我们需要丢弃一些值,我们想要的数字范围为1-40,不在此范围则丢弃并重新取样。
代码:
由于row范围为1-7,col范围为1-7,这样idx值范围为1-49。大于40的值被丢弃,这样剩下1-40范围内的数字,通过取模返回。下面计算一下得到一个满足1-40范围的数需要进行取样的次数的期望值:
优化:
上面的方法大概需要2.45次调用rand7函数才能得到1个1-10范围的数,下面可以进行再度优化。
对于大于40的数,我们不必马上丢弃,可以对41-49的数减去40可得到1-9的随机数,而rand7可生成1-7的随机数,这样可以生成1-63的随机数。对于1-60我们可以直接返回,而61-63则丢弃,这样需要丢弃的数只有3个,相比前面的9个,效率有所提高。而对于61-63的数,减去60后为1-3,rand7产生1-7,这样可以再度利用产生1-21的数,对于1-20我们则直接返回,对于21则丢弃。这时,丢弃的数就只有1个了,优化又进一步。当然这里面对rand7的调用次数也是增加了的。代码如下:
这里期望次数为2.21,比起未优化的2.45次减少了大概10%。
已知一个函数rand7()能够生成1-7的随机数,请给出一个函数,该函数能够生成1-10的随机数。
思路:
假如已知一个函数能够生成1-49的随机数,那么如何以此生成1-10的随机数呢?
解法:
该解法基于一种叫做拒绝采样的方法。主要思想是只要产生一个目标范围内的随机数,则直接返回。如果产生的随机数不在目标范围内,则丢弃该值,重新取样。由于目标范围内的数字被选中的概率相等,这样一个均匀的分布生成了。
显然rand7至少需要执行2次,否则产生不了1-10的数字。通过运行rand7两次,可以生成1-49的整数,
1 2 3 4 5 6 7 1 1 2 3 4 5 6 7 2 8 9 10 1 2 3 4 3 5 6 7 8 9 10 1 4 2 3 4 5 6 7 8 5 9 10 1 2 3 4 5 6 6 7 8 9 10 * * 7 * * * * * * *
由于49不是10的倍数,所以我们需要丢弃一些值,我们想要的数字范围为1-40,不在此范围则丢弃并重新取样。
代码:
int rand10() { int row, col, idx; do { row = rand7(); col = rand7(); idx = col + (row-1)*7; } while (idx > 40); return 1 + (idx-1)%10; }
由于row范围为1-7,col范围为1-7,这样idx值范围为1-49。大于40的值被丢弃,这样剩下1-40范围内的数字,通过取模返回。下面计算一下得到一个满足1-40范围的数需要进行取样的次数的期望值:
E(# calls to rand7) = 2 * (40/49) + 4 * (9/49) * (40/49) + 6 * (9/49)2 * (40/49) + ... ∞ = ∑ 2k * (9/49)k-1 * (40/49) k=1 = (80/49) / (1 - 9/49)2 = 2.45
优化:
上面的方法大概需要2.45次调用rand7函数才能得到1个1-10范围的数,下面可以进行再度优化。
对于大于40的数,我们不必马上丢弃,可以对41-49的数减去40可得到1-9的随机数,而rand7可生成1-7的随机数,这样可以生成1-63的随机数。对于1-60我们可以直接返回,而61-63则丢弃,这样需要丢弃的数只有3个,相比前面的9个,效率有所提高。而对于61-63的数,减去60后为1-3,rand7产生1-7,这样可以再度利用产生1-21的数,对于1-20我们则直接返回,对于21则丢弃。这时,丢弃的数就只有1个了,优化又进一步。当然这里面对rand7的调用次数也是增加了的。代码如下:
int rand10Imp() { int a, b, idx; while (true) { a = rand7(); b = rand7(); idx = b + (a-1)*7; if (idx <= 40) return 1 + (idx-1)%10; a = idx-40; b = rand7(); // get uniform dist from 1 - 63 idx = b + (a-1)*7; if (idx <= 60) return 1 + (idx-1)%10; a = idx-60; b = rand7(); // get uniform dist from 1-21 idx = b + (a-1)*7; if (idx <= 20) return 1 + (idx-1)%10; } }下面计算下优化后方法的调用rand7函数的期望次数:
E(# calls to rand7) = 2 * (40/49) + 3 * (9/49) * (60/63) + 4 * (9/49) * (3/63) * (20/21) + (9/49) * (3/63) * (1/21) * [ 6 * (40/49) + 7 * (9/49) * (60/63) + 8 * (9/49) * (3/63) * (20/21) ] + ((9/49) * (3/63) * (1/21))2 * [ 10 * (40/49) + 11 * (9/49) * (60/63) + 12 * (9/49) * (3/63) * (20/21) ] + ... = 2.2123
这里期望次数为2.21,比起未优化的2.45次减少了大概10%。
相关文章推荐
- 已知一个函数rand7()能够生成1-7的随机数,请给出一个函数rand10(),该函数能够生成1-10的随机数。
- 已知一个函数rand7()能够生成1-7的随机数,请给出一个函数rand10(),该函数能够生成1-10的随机数。
- 给你一个能生成1到5随机数的函数,用它写一个函数生成1到7的随机数。 (即,使用函数rand5()来实现函数rand7())
- eclipse 中main()函数中的String[] args如何使用?通过String[] args验证账号密码的登录类?静态的主方法怎样才能调用非static的方法——通过生成对象?在类中制作一个方法——能够修改对象的属性值?
- 生成随机数(取尽量靠后的数值,如total=10 随机数会返回4-10里的一个数)
- 随机数问题--已知有个Random7()的函数,返回1到7随机自然数,让利用这个Random7()构造Random10()随机1~10.
- php随机数怎么获取?一个简单的函数就能生成
- JAVA随机生成一个10以内的随机数
- 已知一个函数f可以得到1-5间的随机数,问怎么得到1-7的随机数
- 给你一个能生成1到5随机数的函数,用它写一个函数生成1到7的随机数。
- 给定一个自定义函数,random5() 可以随机生成1-5之间的随机数,请利用rondom5()定义一个rondom
- 给定一个能生成1到5随机数的函数,如何利用它来生成1到7的随机数。
- 给你一个能生成1到5随机数的函数,用它写一个函数生成1到7的随机数。
- 生成一个一维数组,有10个元素,都用随机数填充,用指针轮询的办法实现函数查找一个数是否存在。
- 十二、函数能够判断一个数字是否是一个素数(并给出一个范围求出这个范围内所有的素数)
- 生成一个一维数组,有10个元素,都用随机数填充,用指针轮询的办法实现函数查找一个数是否存在。
- 开辟一个二维数组,有10*8个元素,用随机数填充,按照下面的方法用函数实现查找一个数是否存在
- 随机生成一个 10 个元素的数组,找到 x 的倍数,并将其值修改成 0.(注意:修改数值使用回掉函数处理)
- 生成一个一维数组,有10个元素,都用随机数填充,用指针轮询的办法实现函数查找一个数是否存在。
- 开辟一个二维数组,有10*8个元素,用随机数填充,按照下面的方法用函数实现查找一个数是否存在