• 给定一个函数rand()能产生0到n-1之间的等概率随机数,问如何产生0到m-1之间等概率的随机数?


    题目:给定一个函数rand()能产生1到n之间的等概率随机数,问如何产生1到m之间等概率的随机数?

      先把问题特殊化,例如原题变为给定一个函数rand5(),该函数可以随机生成1-5的整数,且生成概率一样。现要求使用该函数构造函数rand7(),使函数rand7()可以随机等概率的生成1-7的整数。

      很多人的第一反应是利用rand5() + rand()%3来实现rand7()函数,这个方法确实可以产生1-7之间的随机数,但是仔细想想可以发现数字生成的概率是不相等的。rand()%3 产生0的概率是1/5,而产生1和2的概率都是2/5,所以这个方法产生6和7的概率大于产生5的概率。

      正确的方法是利用rand5()函数生成1-25之间的数字,然后将其中的1-21映射成1-7,丢弃22-25。例如生成(1,1),(1,2),(1,3),则看成rand7()中的1,如果出现剩下的4种,则丢弃重新生成。

      现在来看原题把rand()视为N进制的一位数产生器,那么可以使用rand()*N+rand()来产生2位的N进 制数,以此类推,可以产生3位,4位,5位...的N进制数。这种按构造N进制数的方式生成的随机数,必定能保证随机概率平均。而相反,借助其他方式来使用 rand()产生随机数(如 rand5() + rand()%3 )都是不能保证概率平均的。

      程序实现:

    int random(int m,int n)
    {
        if(n<1||m<1)//输入参数错误
            return -1;
        if(m<2)//小于2则只能生成1
            return 1;
        if(m==n)//和n相同即可
            return rand();
        int max = 0;//组成新n进制数当前位数下最大数
        int k = 0;//随机数
        while(max+1<m)//求得新n进制数当前位数下最大数小于m,则继续放大新n进制数的位数
        {
            k = k*n + rand()-1;//转换成0到n-1的n进制数。一位时0到n-1,两位时0到(n-1)*n+n-1。此时保证了生成0到最大数之间的各个数的概率是相等的 
            max = max*n + n-1;//求n进制数当前位数下的最大数。一位数时n-1,两位数时(n-1)*n+n-1,三位数时(n-1)*n*n+(n-1)*n+n-1
            //随机数超出了范围则重新计算。除m再乘m是为了对生成的k进行分组
            //如m=7,n=5时此处k的范围是0到24,那么25/7=3,3*7=21。
            //因为21、22、23、24都需要重新计算,所以后面返回值k/((max+1)/m)+1就能保证最大值为7了,即20、19、18除3加1都等于7
            //此处也可以不进行分组,直接限定k+1<=m后面返回k即可,这样得到k的概率也是一样的,只不过更不容易得到k,因为大量的k将大于m
            if(max+1>=m && k>=(max+1)/m*m)
            {
                k = 0;
                max = 0;
            }
        }
        return k/(max+1/m)+1;//由上面逻辑保证了在1到m之间且各数生成概率相等
    }
  • 相关阅读:
    Thinking in Java Reading Note(9.接口)
    Thinking in java Reading Note(8.多态)
    Thinking in Java Reading Note(7.复用类)
    SQL必知必会
    Thinking in Java Reading Note(5.初始化与清理)
    Thinking in Java Reading Note(2.一切都是对象)
    鸟哥的Linux私房菜笔记(1.基础)
    Thinking in Java Reading Note(1.对象导论)
    CoreJava2 Reading Note(2:I/O)
    CoreJava2 Reading Note(1:Stream)
  • 原文地址:https://www.cnblogs.com/budapeng/p/3298108.html
Copyright © 2020-2023  润新知