利用rand5得到rand7

原题:

现有函数rand5可以等概率地生成1~5,要求利用rand5来得到rand7,rand7需可以等概率地生成1~7

思考

1. 我们会想当然地以为rand5() + rand5()即可得到结果[2~10],其实细想一下,但是[2~10]之间的数字并不是等概率的,比如2只有一种可能(1+1),而3有两种可能(1+2, 2+1),6的可能性就更大了(1+5,  2+4,  3+3,  4+2,  5+1),很明显,这些数字不是等概率

2. 换个思路,rand5的结果是1,2,3,4,5等概率,那5*rand5的结果是5,10,15,20,25,且也是等概率。我们只需要把 5, 10, 15, 20, 25 之间数字等概率地填满即可,比如

5之前,等概率地补上1,2,3,4,最终变成1,2,3,4,5,实现方法:5*0+rand5()

(5,10)之间,等概率地补上6,7,8,9,最终变成6,7,8,9,10,实现方法:5*1+rand5()

(10,15)之间,等概率地补上11,12,13,14,最终变成11,12,13,14,15,实现方法:5*2+rand5()

(15,20)之间,等概率地补上16,17,18,19,最终变成16,17,18,19,20,实现方法:5*3+rand5()

(20,25)之间,等概率地补上21,22,23,24,最终变成21,22,23,24,25,实现方法:5*4+rand5()

这样从1~25,之间全部的数字都是等概率

结果:能生成1-25等概率数字,遇到超过7的数字重新生成即可,直到落在1~7之间,即rand7函数

上面规律:

5*(rand5()-1)+rand5() 可以等概率地生成1-25之间的数字

总结一下:

若randN可以等概率生成1~N,那么N * (randN - 1) + randN 可以等概率地生成1-N*N之间的数字

扩散一下:

若randN可以等概率生成1~N,那么我们可以必定可以等概率地生成1-N*N,依新函数为基础,再来一次,可以等概率地生成1 ~ N*N*N*N。如下

根据rand5()可以得到rand25()

根据rand25()可以得到rand625()

int rand5()   { return rand()%5+1;}
int rand25()  { return 5*(rand5()-1)+rand5();}
int rand625() { return 25*(rand25()-1)+rand25();}

好了,现在我们给出rand7的代码

代码做了一处优化,并不是简单把7以上的数字重新生成,而是做了取余7,这样1~21的数字都不用重试,只有遇到22及以上数字才重试,效率更高一点儿

#include 
using namespace std;

int rand5() { return rand()%5+1;}

int rand7()
{
    int x = 22;
    while (x > 21)
    {
        x = 5*(rand5()-1)+rand5();
    }
    return 1 + x%7;
}

int main()
{   
    srand(time(0));
    for (int i=0; i<10; i++)
    {
        cout<

执行效果如下图

利用rand5得到rand7_第1张图片

你可能感兴趣的:(概率论,rand5生成rand7,rand5,rand7,rand5,rand7)