题目:
1、一个函数fun()均匀返回0和1,各自的概率是50%,利用这个函数实现一个函数,使之返回 1的概率为3/4,0的概率为1/4。
2、假如有一个函数rand5能等概率生成1 - 5 之间的整数,如何利用rand5来实现rand7?rand7函数的要求是能够等概率生成1 - 7之间的整数。
思路:
- C++的随机函数rand()和srand():
所在的头文件:<stdlib.h>
函数一:int rand(void);
从srand (seed)中指定的seed开始,返回一个[seed, RAND_MAX(0x7fff))间的随机整数。
函数二:void srand(unsigned seed);
参数seed是rand()的种子,用来初始化rand()的起始值。
如果希望rand()在每次程序运行时产生的值都不一样,必须给srand(seed)中的seed一个变值,这个变值必须在每次程序运行时都不一样(比如到目前为止流逝的时间), srand((unsigned) time(NULL));
- 题目1:
思路有很多,
例如fun()+fun(),0,1相加可以得到3个值,0+0=0;0+1=1;1+0=1;1+1=2,以0为界分成两类,等于0为0,大于0为1,则新生成0的概率为1/4,新生成1的概率为3/4;
例如fun()*fun(),0,1相乘可以得到2个值,0*0=0;0*1=0;1*0=0;1*1=1,同样分成两类,等于0为1,等于1为0,则新生成0的概率为1/4,新生成1的概率为3/4;
还有其他方法,例如pow(fun(),fun()),fun()-fun()等等,只要能找到1:3的一个分界即可。
- 题目2:
第二题不能直接通过rand5()基本运算得到1-7的一个均匀分布,例如rand5()+rand5()得不到1-10之间的均匀分布。生成6(2+4,4+2,3+3)的概率大于生成1(0+1,1+0)的概率。
既然不能通过运算得到结果,我们可以构造一个更大的数据范围,例如7的倍数。如何构造呢?通过两个rand5()来生成两个独立分布,独立意味着不重复,可以很容易想到通过(rand5()-1)*5和rand5()-1来生成两个独立均匀分布,第一个生成0,5,10,15,20的均匀分布,第二个生成0,1,2,3,4的均匀分布,将两者相加,即(rand5()-1)*5+rand5()-1就可以得到0-24的一个均匀分布,取7的倍数个数,例如21个,即0-20,再加上1就得到1-21的均匀分布,进而%7就得到rand7()。
切记不能通过rand5()*6-6来做,因为我们需要的是两个独立的分布。
还有一个方法,从二进制的角度来思考,生成1-7的均匀分布,在二进制中,只需三位,如果每一位0,1的生成也是均匀的话(通过rand5()可以得到),那么就可以得到0-7的均匀分布,生成0时不予考虑即可以得到1-7的均匀分布,具体参考代码。
代码:
题目1:
#include <iostream> #include <stdlib.h> #include <time.h> using namespace std; int fun(){ return rand()%2; } int fun2(){ int i=fun()+fun(); if(i>0) return 1; else return 0; } /* int fun2(){ int i=fun()*fun(); if(i==0) return 1; else return 0; } */ int main() { int sum_1=0; int sum_0=0; srand((unsigned)time(0)); for(long long i=0;i<999999;i++){ if(fun2()==1) sum_1++; else sum_0++; } cout<<sum_1<<":"<<sum_0<<endl; cout<<(float)sum_1/sum_0<<endl; return 0; }
题目2:
#include <iostream> #include <stdlib.h> #include <time.h> using namespace std; int rand5(){ return rand()%5+1; } // generate 0,1 int rand01(){ int i=rand5(); if(i>4) return rand01(); return i%2; } int rand7_1(){ int i; while(true){ // generate 0-24 i=(rand5()-1)*5+rand5()-1; if(i<21) return i%7+1; } } int rand7_2(){ int i; // generate 0-7 i=(rand01()<<2)+(rand01()<<1)+rand01(); if(i==0) i=rand7_2(); return i; } int main() { srand((unsigned)time(0)); int A[7]={0,0,0,0,0,0,0}; int B[7]={0,0,0,0,0,0,0}; for(long long i=0;i<99999999;i++){ A[rand7_1()-1]++; B[rand7_2()-1]++; } for(int i=0;i<7;i++) cout<<A[i]<<" "; cout<<endl; for(int i=0;i<7;i++) cout<<B[i]<<" "; cout<<endl; return 0; }