/************************************************************************** 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; }