利用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的数字啦。
相关文章推荐
- 利用Random类产生5 个1-30之间(包括1和20)的随机整数。
- 利用shell/bask产生随机字符串
- 利用Random类产生5 个1-30之间(包括1和20)的随机整数。
- 利用Random类产生5 个1-30之间(包括1和20)的随机整数。
- 利用Random类来产生5个20~50之间的随机整数
- C++中的srand(time(null))利用时间设置随机种子产生随机数
- 一个产生随机数字 字符串验证码 日期的类扩展实现
- 随机产生线性模型的线条 利用RNG的类
- 利用PHP产生随机验证码
- 利用均匀分布产生随机的正态分布的数据输入源
- unity中利用C#产生随机不相同的一组数
- 随机产生值不重复的一维数组,并求①最小值,②次小值,③最大值及其索引
- 利用Random类产生5 个1-30之间(包括1和20)的随机整数。
- 利用rand5()产生rand7() 扩展:randn()
- C++中的srand(time(null))利用时间设置随机种子产生随机数
- 利用Random类产生5 个1-30之间(包括1和20)的随机整数。
- C++中的srand(time(null))利用时间设置随机种子产生随机数
- 利用Random类产生5 个1-30之间(包括1和20)的随机整数。
- C++中的srand(time(null))利用时间设置随机种子产生随机数
- 利用Random类产生5 个1-30之间(包括1和20)的随机整数。