您的位置:首页 > 其它

利用5随机产生7随机及其扩展

2017-04-30 23:37 330 查看

原题

题目

给出一个随机产生1到5的函数,不适用其它随机函数的前提下,设计算法返回随机产生1到7的的数字。

思路

假设原始函数为rand1to5(),它能够随机的产生1,2,3,4,5这5个数字。

那么rand1to5() - 1能够随机产生0,1,2,3,4这5个数字。

那么(rand1to5() - 1) * 5能够随机产生0, 5, 10, 15, 20这5个数字。

那么(rand1to5() - 1) * 5 + rand1to5() - 1能够随机产生0到24之间的所有数字,假设用t来保存这个数值。(注意,因为分别两次使用了rand1to5()这个函数,实际上这两次产生的值是没有关联的)

如果t大于20的话,那么重新计算一次(rand1to5() - 1) * 5 + rand1to5() - 1,一直到t小于等于20,由于大于20的概率是随机的,所以可以认为随机产生了0到20之间的21个数字。

这样t % 7 + 1就可以随机产生1到7之间的数字了。

代码

#include<iostream>
#include<cstdlib>
#include<ctime>
using namespace std;

// 随机产生1到5的数字
int getRand1to5() {
return rand() % 5 + 1;
}

// 利用getRand1to5来随机生成1到7
int Rand1to7() {
int t = (getRand1to5() - 1) * 5 + getRand1to5() - 1;
while(t > 20) t = (getRand1to5() - 1) * 5 + getRand1to5() - 1;
return t % 7 + 1;
}

int main() {
srand((unsigned int)time(NULL));
int num[8] = {0}; // 测试1到7中的数字出现的次数
for (int i = 0; i < 70000; ++i) {
num[Rand1to7()]++;
}
for (int i = 1; i <= 7; ++i) {
cout << "rand" << i << " " << num[i] << endl;
}
return 0;
}


参考结果



扩展

题目1

有个函数以p概率返回0,1-p的概率返回1,用这个函数随机产生1到6的数字。

思路

假设这个函数是rand0to1(),调用它两次,第一次是0,第二次是1(即01)的概率是p * (1 - p),第一次是1,第二次是0(即10)的概率是(1 - p)* p,他们的概率是一样的,即可以随机产生01和10,此时只要取第一次(或者取第二次)产生的数就可以随机产生0和1了,假设为rand0and1();

同上面的做法,rand0and1() * 2 可以随机产生0和2;

那么rand0and1() * 2 + rand0and1()可以随机产生0,1,2,3,记为rand0to3().

那么rand0to3() * 2可以随机产生0,2,4,6;

那么rand0to3() * 2 + rand0and1(),可以随机产生0,1,2,3,4,5,6,7,记为t

如果t>5就重新计算rand0to3() * 2 + rand0and1(),一直到t <= 5;

那么t % 6 + 1就能随机产生1到6的数字了。

参考代码

#include<iostream>
#include<cstdlib>
#include<ctime>
using namespace std;
double p;

// 以p概率产生0, 1-p概率产生1
int rand0to1() {
double t = 1.0 * rand() / RAND_MAX;
if (t < p) return 0;
else return 1;
}

// 随机产生0和1
int rand0and1() {
int t;
do {
t = rand0to1();
} while (t == rand0to1());
return t;
}

// 随机产生0,1,2,3
int rand0to3() {
return rand0and1() * 2 + rand0and1();
}

// 得到随机1到6的数字
int getRand1to6() {
int t;
do {
t = rand0to3() * 2 + rand0and1();
} while (t > 5);
return t % 6 + 1;
}

int main() {
srand((unsigned int)time(NULL));
for (int i = 0; i < 3; ++i) {
cout << "enter p : ";
cin >> p;
int num[7] = { 0 };
for (int j = 0; j < 10000; ++j) {
num[getRand1to6()]++;
}
for (int j = 1; j <= 6; ++j) {
cout << "rand " << j << " " << num[j] << endl;
}
}
return 0;
}


参考结果



题目2

给定任意一个随机产生1到m的随机函数,用它设计一个随机产生1到n的算法。

思路

假设随机产生1到m的函数为rand1tom();

首先,如果n<=m的话,那么可以直接使用rand1tom()一直到产生的值在1到n之间即可。这是因为1,2,3。。。m之间的数字都是随机输出的,那么产生1,2,3。。。n的概率都是一样的,并且产生n + 1,n + 2,。。。m的概率会平摊到前面1到n上去。

如果n > m的话:

(rand1tom() - 1) * m + rand1tom()可以随机产生1到m * m之间的数字,记为rand1tom2();

同上一步的步骤,用(rand1tom2() - 1) * m * m + rand1tom2()可以随机产生1到m的四次方之间的数字,一直循环下去,直到随机产生的范围大于等于n。

此时把不满足n的整数倍的部分去掉,剩下的取余就可以得到随机产生的1到n的数字啦。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  函数 算法