两个rand5生成rand7

/**************************************************************************
Author: Rita
Descrption: 写此程序源于某公司的一个面试题。
    已知条件:假设已经得到一个rand5()函数:可以随机产生0 ~ 4 这5个数
    问题:要求利用两个rand5(),得到一个rand7(),即可随机产生0 ~ 6 这7个数。
    算法思路:
        随机函数的一个最重要的特点就是均匀分布,即产生每一个数的概率相等。
        显然,rand5()是以等概率生成0 ~ 4 这5个数的。因此,rand7()函数也
        必须以等概率生成0 ~ 6 这7个数。

    算法1:rand7_ref1()
        将第一次rand5()生成的数num1和第二次rand5()生成的数num2组合相加,
        可以等概率得到0 ~ 24 这25个数。具体可用如下方式表示:
                0  5  10  15  20
             0  0  5  10  15  20
             1  1  6  11  16  21
             2  2  7  12  17  22
             3  3  8  13  18  23
             4  4  9  14  19  24

         为了等概率得到0 ~ 6 这7个数,可以从上面生成的25个数中取出个数为
         7的最大倍数(21)个数,即将21,22,23,24这4个数舍弃。然后将0~20
         这21个数 %7(取模)即可。
 
    算法2:rand7_ref2() 
         利用计算机中数字的二进制表示法,可以用三位二进制数来表示0 ~ 6 这7个数。
         step1: 先用rand5()生成rand2(),思路与算法1类似。
                rand5()生成0 ~ 4 这5个数,从中取出个数为2的最大公倍数(4)个数,舍弃4,
                然后将0 ~ 3 这4个数 % 2即可得到rand2()。

         step2: 再用rand2()生成rand7()
                rand7() = rand2() << 2 + rand2() << 1 + rand2(); 
                
Date: 2012.09.29
****************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

#define TEST_TIMES  10000

/*************************************
算法1: 
从两次rand5()产生的25个组合数
0 ~ 24 中取出前面的21个模7               
*************************************/
int rand7_ref1()
{
   int num1 = 0, num2 = 0;
   int val = 0;
   int result=0;
do
{ 
   num1 = rand()%5;
   num2 = rand()%5;
   val = 5*num1 + num2;

   if ( val < 21)
   {
      result = val % 7;
   }

}while( val >= 21 );

   return result;
}

/*************************************
测试算法1是否满足均匀分布
*************************************/
int test_rand7_ref1()
{
   int i;
   int num = 0;
   int count[7];

   for ( i = 0; i < 7; i++)
   {
      count[i] = 0;
   }

   for ( i = 0 ; i < TEST_TIMES ; i++ )
   { 
      num = rand7_ref1();
      count[num]++;
   }

   printf("判断算法1是否均匀生成 0 ~ 6:\n");
   for ( i = 0 ;i < 7; i++ )
   {
      printf("count[%d]=%.3f\n",i,(float)count[i]/TEST_TIMES);
   }

   return 1;
}

/**************************************
    rand5()生成rand2():等概率得到0和1
***************************************/
int rand5_to_rand2()
{
   int num1=0 , num2=0;
   do
   {
      num1 = rand()%5;

      if ( num1 < 4 )
      {
         num2 = num1 % 2;
      }

    }while( num1 == 4);

    return num2;
}

/************************************** 
测试是否等概率得到0和1
***************************************/
void test_rand5_to_rand2()
{
    int i, result = 0;
    int count[2];

    for ( i = 0; i < 2; i++)
    {
       count[i] = 0;
    }

    for( i = 0 ; i < TEST_TIMES; i++ )
    { 
       result = rand5_to_rand2();
       count[result]++;
    }

    printf("判断是否均匀生成 0 ~ 1:\n");
    for ( i = 0; i< 2; i++ )
    {
       printf("count[%d]=%.3f\n",i,(float)count[i]/TEST_TIMES);
    }
}

/************************************** 
由三位二进制数生成rand7()
***************************************/
int rand7_ref2()
{
   int bit[3],result=0;

   bit[0] = rand5_to_rand2();
   bit[1] = rand5_to_rand2()<<1;
   bit[2] = rand5_to_rand2()<<2;
   result = bit[2] + bit[1] + bit[0];

   return result;
}

/************************************** 
测试是否等概率得到0 ~ 6
***************************************/
void test_rand7_ref2()
{
    int i,result;
    int count[7];

    for ( i = 0; i < 7; i++ )
    {
       count[i] = 0;
    }

    for ( i = 0 ; i < TEST_TIMES; i++ )
    { 
       result = rand7_ref2();
       count[result]++;
    }

    printf("判断算法2是否均匀生成 0 ~ 6:\n");
    for ( i = 0 ;i < 7; i++ )
    {
       printf("count[%d]=%.3f\n",i,(float)count[i]/TEST_TIMES);
    }
}

int main()
{ 
    srand(time(NULL));
    test_rand5_to_rand2();
    test_rand7_ref1();
    test_rand7_ref2();
    return 1;
}

运行结果:
判断是否均匀生成 0 ~ 1:
count[0]=0.496
count[1]=0.504


判断算法1是否均匀生成 0 ~ 6:
count[0]=0.150
count[1]=0.149
count[2]=0.145
count[3]=0.141
count[4]=0.136
count[5]=0.139
count[6]=0.141


判断算法2是否均匀生成 0 ~ 6:
count[0]=0.126
count[1]=0.125
count[2]=0.123
count[3]=0.119
count[4]=0.126
count[5]=0.125
count[6]=0.125




评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值