题目:
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;
}