首页 > 代码库 > 利用随机函数生成随机数

利用随机函数生成随机数

给定一个rand(),可以产生从0到RAND_MAX的随机数,其中RAND_MAX很大(常见值:16位int能表示的最大整数32767),写出利用rand()生成[a,b]中任意整数的函数,其中a>=0, b<=RAND_MAX,且b-a<<RAND_MAX.

分析:

这是在编程工作最常见的随机函数的应用,在这里做一个起点再合适不过。把随机数区间的起点从0变为a,同时把一共RAND_MAX+1个数的区间缩小至只含有b-a+1个数的区间,写为 a + rand()%(b-a+1),此时显然最大值是a+(b-a)= b。

进一步地,这个b-a<<RAND_MAX的条件虽然看上去不起眼,其实很重要。

附加思考:

如果b-a和RAND_MAX很接近会发生什么情况?读者不妨先做思考,问题2的分析会做出解答。

这个rand(),其实相当于《编程珠玑》提到的bigrand()。

假设:一个能返回很大随机整数的的函数bigrand(),一个能返回i..j范围内均匀选择的随机整数函数randint(i,j)。
  在C语言中,随机函数rand()通常返回约15个随机位,可以使用该函数实现上述bigrand()和randint()函数。

  int bigrand(){
      return RAND_MAX*rand() + rand();
  }
  int randint(int l, int u){
      return l + bigrand() % (u-l+1);
  }

给定一个随机数函数rand7(),它能以等概率生成1~7这7个整数。请根据rand7()写出类似的rand5()。

分析:

如果直接像问题1中一样,把1+rand7()%5作为rand5()会有什么情况发生?这时确实能产生1~5的随机数没错,可是各个数的概率相等吗?

对于随机数2,既有可能来自于1+1%5,也有可能来自于1+6%5,显然其概率是2/7,而不是1/5,不满足rand5()等概率产生各随机数这一隐含要求。不同于问题1,问题1中一个很大的区间收缩成较小区间时,各个元素映射后的新元素概率虽然概率可能不完全一样,但却是近似相同的。

  为了满足等概率的要求,可以这么做:

int rand5() {
    int res;
    do {
        res = rand7();
    } while(t>=6);
    return res;
} 

虽然保证了1~5的概率都变成了1/5,但是有一个无法避免的缺点是,每当产生了6或者7都要抛弃,相当于这一次运行是“空转”,浪费了时间。

如果对1/5这个概率不明白,可以有两种理解:每次产生6或7就被抛弃,剩下数的概率相等,必然为1/5;或者用更严密的推理:产生1~5的随机数,最终得到某一个的概率为:1/7+(1/7)*(2/7)+(1/7)*(2/7)2+...,无限项求和,结果是1/5。

 给定一个随机数函数rand7(),它能以等概率生成1~7这7个整数。请根据rand7()写出类似的rand10()。

分析:

  有了问题2的概率基础,把rand7()变成rand10()仅仅需要一点点思考了。

int rand10() {
    int t1,t2,res;
    do {
        t1 = rand7();
    } while(t1>=6);
    //t1以等概率成为1/5

    do {
        t2 = rand7();
    } while(t2==7); 
    //t2以1/2概率成为奇数或偶数

    res = t1+5*(t2%2);
    //res是1~10中的任意一个数的概率都是1/10
    //注意到%和*具有相同的优先级,这里去掉括号结果是错的    
    return res;
}

等概率的rand10()

等概率的rand10()

给定能随机生成整数1到5的函数,写出能随机生成整数1到7的函数。

利用随机函数rand()函数生成一个等概率随机生成整数1到5的函数Rand5(),然后根据Rand5()生成Rand7(),代码如下:

int Rand5()  
{  
    int n =1 + rand()%5;  
    return n;  
}  
int Rand7()  
{     
    int n ,tmp1 ,tmp2;    
    do   
    {  
        tmp1 = Rand5();  
        tmp2 = Rand5();  
        n = (tmp1-1)*5+tmp2;//n是可以取1~25的随机的数。  
    } while (n>21);//当n>21舍去,这样n只能取1~21,对7取模就能取1~7之间的随机数  
  
    return 1+n%7;  
    }  


参考https://linhan.blog.ustc.edu.cn/?p=408

http://www.cnblogs.com/wuyuegb2312/p/3141292.html#title1

利用随机函数生成随机数