一道面试题:等概率随机数

题目:

假设有两个函数 rand3()可以产生随机的0、1、2,rand5()可以产生随机的0、1、2、3、4,现在请你利用它编写一个函数rand7(),产生0~6的随机数。

方法1:利用数组

int rand7()
{
    int a[3][3]={ 0,1,2,3,4,5,6,7,8 };
    int row,col;
    do 
    {
        row = rand3();
        col = rand3();
    } while(a[row][col]>6);

    return a[row][col];
}

方法2:利用switch语句

int rand7()
{
    int re;
    do 
    {
        switch( rand3() )
        {
        case 0:
            re = rand3();
            break;
        case 1:
            re = rand3()+3;
            break;
        case 2:
            re = rand3()+6;
            break;
        }
    } while(re>6);

    return re;
}

方法3:更简洁,实质和方法2相同

int rand7()
{
    int re;

    do
    {
        re = rand3()+rand3()*3;
    }while(re>6);

    return re;
}

测试代码:

#include 
#include 
#include 

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

int rand3()
{   return rand()%3;    }

int rand7()
{
    int a[3][3]={ 0,1,2,3,4,5,6,7,8 };
    int row,col;
    do 
    {
        row = rand3();
        col = rand3();
    } while(a[row][col]>6);

    return a[row][col];
}

//从均匀的0~20里面取mod
int rand7a() {

    int sum = 0;
    for (int i=0;i<7;i++) {
        sum+= rand3()+i*3;
    }
    return sum%7;
}

//从均匀的0~34里面取mod
int rand7b() {

    int sum = 0;
    for(int i=0;i<7;i++) {
        sum += rand5()+i*5;
    }
    return sum%7;
}

void main()
{ 
    int re[7]={0};

    srand( (unsigned)time( NULL ) );
    for(int i=0;i<1000000;i++)
    {
        re[rand7()]++;
    }

    for(int i=0;i<7;i++)
    printf("re[%d]=%d,%2d%%\n",i,re[i],int(re[i]*100/1000000.0+0.5));
}

运行结果:

re[0]=143047, 14%
re[1]=143042, 14%
re[2]=143561, 14%
re[3]=143315, 14%
re[4]=142750, 14%
re[5]=142144, 14%
re[6]=142141, 14%
请按任意键继续. . .

错误方法:

//从均匀的0~20里面取mod
int rand7a() {

    int sum = 0;
    for (int i=0;i<7;i++) {
        sum+= rand3()+i*3;
    }
    return sum%7;
}

//从均匀的0~34里面取mod
int rand7b() {

    int sum = 0;
    for(int i=0;i<7;i++) {
        sum += rand5()+i*5;
    }
    return sum%7;
}

错误方法分析:

  • rand7a()在测试时就发现产生数字的概率不平均,rand7b()在测试时产生的概率是平均的,而这两种方法的原理相同,为什么会这样?
  • rand7a()中加到sum中的数字之和为:0+3+6+…+18=63,63%7=0,所以实质是sum=7个rand3()之和。sum有 37=2178 个结果,不是7的倍数,概率是不平均的。
  • rand7b()原理是一样的,所以概率也是不平均的。但在测试时结果是平均的,可能是因为sum有 57=78125 个结果,必须增大测试数据量才行。
  • 在实际测试时用了900000000个数据,rand7b()的结果概率仍然平均的。不知道是为什么?如果哪位网友找到了原因,请留言,分享一下。

参考:

本文是根据在CSDN问答频道和网友讨论一个问题的帖子整理而成。
该贴链接

你可能感兴趣的:(C++基础,随机数,面试题,C,C++)