• (算法)关于随机数的生成


    题目:

    1、一个函数fun()均匀返回0和1,各自的概率是50%,利用这个函数实现一个函数,使之返回 1的概率为3/4,0的概率为1/4。

    2、假如有一个函数rand5能等概率生成1 - 5 之间的整数,如何利用rand5来实现rand7?rand7函数的要求是能够等概率生成1 - 7之间的整数。

    思路:

    • C++的随机函数rand()和srand():

      所在的头文件:<stdlib.h>

      函数一:int   rand(void); 
          从srand   (seed)中指定的seed开始,返回一个[seed,   RAND_MAX(0x7fff))间的随机整数。 

      函数二:void   srand(unsigned   seed); 
          参数seed是rand()的种子,用来初始化rand()的起始值。 

      如果希望rand()在每次程序运行时产生的值都不一样,必须给srand(seed)中的seed一个变值,这个变值必须在每次程序运行时都不一样(比如到目前为止流逝的时间), srand((unsigned) time(NULL)); 

    • 题目1:

      思路有很多,

      例如fun()+fun(),0,1相加可以得到3个值,0+0=0;0+1=1;1+0=1;1+1=2,以0为界分成两类,等于0为0,大于0为1,则新生成0的概率为1/4,新生成1的概率为3/4;

      例如fun()*fun(),0,1相乘可以得到2个值,0*0=0;0*1=0;1*0=0;1*1=1,同样分成两类,等于0为1,等于1为0,则新生成0的概率为1/4,新生成1的概率为3/4;

      还有其他方法,例如pow(fun(),fun()),fun()-fun()等等,只要能找到1:3的一个分界即可。

    • 题目2:

      第二题不能直接通过rand5()基本运算得到1-7的一个均匀分布,例如rand5()+rand5()得不到1-10之间的均匀分布。生成6(2+4,4+2,3+3)的概率大于生成1(0+1,1+0)的概率。

      既然不能通过运算得到结果,我们可以构造一个更大的数据范围,例如7的倍数。如何构造呢?通过两个rand5()来生成两个独立分布,独立意味着不重复,可以很容易想到通过(rand5()-1)*5和rand5()-1来生成两个独立均匀分布,第一个生成0,5,10,15,20的均匀分布,第二个生成0,1,2,3,4的均匀分布,将两者相加,即(rand5()-1)*5+rand5()-1就可以得到0-24的一个均匀分布,取7的倍数个数,例如21个,即0-20,再加上1就得到1-21的均匀分布,进而%7就得到rand7()。

      切记不能通过rand5()*6-6来做,因为我们需要的是两个独立的分布。

      还有一个方法,从二进制的角度来思考,生成1-7的均匀分布,在二进制中,只需三位,如果每一位0,1的生成也是均匀的话(通过rand5()可以得到),那么就可以得到0-7的均匀分布,生成0时不予考虑即可以得到1-7的均匀分布,具体参考代码。

    代码:

    题目1:

    #include <iostream>
    #include <stdlib.h>
    #include <time.h>
    
    using namespace std;
    
    int fun(){
        return rand()%2;
    }
    
    int fun2(){
        int i=fun()+fun();
        if(i>0)
            return 1;
        else
            return 0;
    }
    /*
    int fun2(){
        int i=fun()*fun();
        if(i==0)
            return 1;
        else
            return 0;
    }
    */
    int main()
    {
        int sum_1=0;
        int sum_0=0;
        srand((unsigned)time(0));
        for(long long i=0;i<999999;i++){
            if(fun2()==1)
                sum_1++;
            else
                sum_0++;
        }
        cout<<sum_1<<":"<<sum_0<<endl;
        cout<<(float)sum_1/sum_0<<endl;
        return 0;
    }
    

      

    题目2:

    #include <iostream>
    #include <stdlib.h>
    #include <time.h>
    
    using namespace std;
    
    int rand5(){
        return rand()%5+1;
    }
    
    // generate 0,1
    int rand01(){
        int i=rand5();
        if(i>4)
            return rand01();
        return i%2;
    }
    
    int rand7_1(){
        int i;
        while(true){
            // generate 0-24
            i=(rand5()-1)*5+rand5()-1;
            if(i<21)
                return i%7+1;
        }
    }
    
    int rand7_2(){
        int i;
        // generate 0-7
        i=(rand01()<<2)+(rand01()<<1)+rand01();
        if(i==0)
            i=rand7_2();
        return i;
    }
    
    int main()
    {
        srand((unsigned)time(0));
        int A[7]={0,0,0,0,0,0,0};
        int B[7]={0,0,0,0,0,0,0};
        for(long long i=0;i<99999999;i++){
            A[rand7_1()-1]++;
            B[rand7_2()-1]++;
        }
        for(int i=0;i<7;i++)
            cout<<A[i]<<" ";
        cout<<endl;
        for(int i=0;i<7;i++)
            cout<<B[i]<<" ";
        cout<<endl;
        return 0;
    }
  • 相关阅读:
    More on wrapper types
    使用Solr索引MySQL数据
    Java线程池
    Jedis-returnResource使用注意事项
    sh脚本异常,binsh^M bad interpreter No such file or directory
    Java集合类从属关系
    SonarQube+Jenkins,搭建持续交付平台
    初始化块和静态初始化块的区别
    从SonarQube谈设计模式
    Github+Hexo,搭建专属网站
  • 原文地址:https://www.cnblogs.com/AndyJee/p/4600431.html
Copyright © 2020-2023  润新知