论坛中看到了帖子,http://topic.csdn.net/u/20111001/05/3d6fac8d-21ec-4dda-ad15-7a7076065e32.html
内容如下:
rand7是一个能生成1-7的随机数。要求利用rand7生成1-10的随机数。
之前看过这贴子,找不到了。。。再来问问。
要求:
不可以用这样的方法: 生成rand7() 如果 rand7()>5。重新来过。我的意思是要确保你的函数在任何的情况下都能在一个流程产生结果(可以用多次rand7())。总之就是不准有无限递归或循环。
之前也看到过这道题尝试了一下没有什么思路,但是经过看到10楼回帖发现一个思路很好,但是他们没有继续推敲下去还存在问题,因为得到的随机数中2,3的概率是大于其他的。
10楼回复:
int rand10() { int sum=0; for(int i=0; i<10; i++) sum=7*sum+rand7()-1; return sum%10+1; }
首先这里的循环10次没有根据,但引用了7进制的 方法,可以保证得到的数是均匀分布的只是6666666666(7进制表示)是不可以被10整除的,余数为2,所以得到2,3的概率是大于其他的数。
但是这个思路是可以引用的,只要保证得到7进制数的最大值是10的倍数即可。经计算器尝试,4位数即可。也就是6666(7的4次幂是2401,所以6666=7的4次幂-1所以为2400)换成10进制为2400.得到数的区间为0-2400且均匀分布。所以这样取余后得到的rand10保证概率相同。
改进后代码如下:
int rand10()
{
int sum=0;
for(int i=0; i<4; i++)
sum=7*sum+rand7()-1;
return sum%10+1;
}
20190731再翻出来看发现存在误区
产生的数据2401个,实际并不是概率平均。1-10,11-20,。。。。2391-2400.实际0的概率大。
如果采用7进制则需要数据分布为0-9,10-19,这样9结尾的数据才可以。但7是奇数所以不会产生0结尾的数(7的n次幂-1=0则需要7的n次幂为0结尾)。被PASS掉了。
如果8进制则可以为1-10,11-20,这样可以被10整除的数即可。8进制感觉也不会产生10结尾的数呢?
无解了待续
如果采用丢弃0,则均匀分布单不符合楼主不可丢弃的要求。