题目:
已知随机函数发生器f(x)能够以相等的概率生成1到5这5个正整数。现在要以它为元件来编程制造一个新的随机函数发生器g(x),要求g(x)能够以相等的概率生成1到9这9个正整数,请简要描述你的设计方案。
第一种解法:
利用rand5()函数生成1-25之间的数字,然后将其中的1-18映射成1-9,丢弃19-25。也就是说1、2对应rand9()函数生成的1,3、4对应rand9()函数生成的2,依此类推。这里1-25个数字的生成使用代
码“a=rand5()*5+rand5()”,但并不等同于“a=rand5()*6”这样无法满足等概率了。
#include <iostream> #include <math.h> using namespace std; int rand5() { return rand()%5+1; } int rand9() { int a; while( (a=rand5()*5+rand5()) > 24 ); return (a-4)/2; } int main(int, char **) { srand((unsigned)time(NULL)); int num; cout << "输入总生成数:"; cin >> num; int c1, c2, c3, c4, c5, c6, c7,c8,c9; c1 = c2 = c3 = c4 = c5 = c6 = c7 = c8 = c9 = 0; for (int i = 0; i < num; i++) { int temp = rand9(); switch (temp) { case 1: c1++; break; case 2: c2++; break; case 3: c3++; break; case 4: c4++; break; case 5: c5++; break; case 6: c6++; break; case 7: c7++; break; case 8: c8++; break; case 9: c9++; } } cout << endl; cout << "生成1的个数占总生成数的:" << (double)c1/num*100 << "%" << endl; cout << "生成2的个数占总生成数的:" << (double)c2/num*100 << "%" << endl; cout << "生成3的个数占总生成数的:" << (double)c3/num*100 << "%" << endl; cout << "生成4的个数占总生成数的:" << (double)c4/num*100 << "%" << endl; cout << "生成5的个数占总生成数的:" << (double)c5/num*100 << "%" << endl; cout << "生成6的个数占总生成数的:" << (double)c6/num*100 << "%" << endl; cout << "生成7的个数占总生成数的:" << (double)c7/num*100 << "%" << endl; cout << "生成8的个数占总生成数的:" << (double)c8/num*100 << "%" << endl; cout << "生成9的个数占总生成数的:" << (double)c9/num*100 << "%" << endl; system("pause"); return 0; }运行结果如下图所示。
可以看出1-9每个数字出现的频率是很均等的。
第二种解法:
我们可以调用 n 次rand5(),生成 n 个 1 到 5 之间的随机数,选取最大数所在位置即可满足以上要求。例如,初始的 9个数 [1,2,3,4,5,6,7,8,9],7 个 1 到 5 的随机数 [1, 3,5,4,2,5,2,5,4],那么我们保留下[3,6,8],3 个1 到 5 的随机数[2,1,3],那么我们保留下[8],8 就是我们这次生成的随机数。
int rand9_subject( int *p, int len) { int max=0,j=0,result; int b[9]={0}; int *q=new int[len]; for(int i =0;i<len;i++) { *(q++)=0; } q=q-1; for(int i=0;i<len;i++) { *q=rand5(); if(max<*q) max=*q; --q; } q=q+1; for(int i=0;i<len;i++) { if(*(q++)==max) b[j++]=*p; ++p; } q=q-len; delete [] q; if(j==1) { result=b[j-1]; return result; } return rand9_subject(b,j); } int rand9() { int list[9]={1,2,3,4,5,6,7,8,9}; return rand9_subject(list,9); }运行结果如下图所示。
#include <iostream> #include <cstdio> #include <ctime> #include <cstdlib> #include <cmath> using namespace std; int rand5() { //随机生成[1-5]之间的随机数 return (rand() % 5 + 1); } int rand9_1() { //第一种解法 int a; while( (a=rand5()*5+rand5()) > 24 ); return (a-4)/2; } int rand9_subject( int *p, int len) { //第二种解法主体代码 int max=0,j=0,result; int b[9]={0}; int *q=new int[len]; for(int i =0;i<len;i++) { *(q++)=0; } q=q-1; for(int i=0;i<len;i++) { *q=rand5(); if(max<*q) max=*q; --q; } q=q+1; for(int i=0;i<len;i++) { if(*(q++)==max) b[j++]=*p; ++p; } q=q-len; delete [] q; if(j==1) { result=b[j-1]; return result; } return rand9_subject(b,j); } int rand9_2() { //第二种解法 int list[9]={1,2,3,4,5,6,7,8,9}; return rand9_subject(list,9); } double variance(int *a, int cnt, int len) { //求均方差 double s = 0; int average = cnt / 9; for(int i = 1; i < len; i++) { s += (a[i] - average) * (a[i] - average) ; } return sqrt(s/cnt); } int main() { srand((unsigned)time(NULL)); int a[10] = {0}; int b[10] = {0}; int a1, a2, cnt, i; cout << "输入总生成数:"; cin >> cnt; i=cnt; while(i--) { a1 = rand9_1(); a2 = rand9_2(); ++a[a1]; ++b[a2]; } cout << endl; cout << "rand9_1()的均方差值为:" << variance(a, cnt, 10) << endl; cout << "rand9_2()的均方差值为:" << variance(b, cnt, 10) << endl; system("pause"); }