新浪博客

产生1-5的随机函数,生成随机数1-7

2013-08-20 00:34阅读:
需求:已知函数f()生成1-5的随机数,求用f()生成1-7的随机数。
先上代码,再说思路。
#include <iostream>
#include <cstdlib> //rand
#include <vector> //vector<int>
#include <algorithm> //count
#include <cmath> //pow
using namespace std;
//generate 1~5
int rand15()
{
return 1 + rand() % 5;
}
//generate 0~1
int rand01()
{
int r = rand15();
if (r
== 3)
return rand01();
if (r < 3)
return 0;
else
return 1;
};
//algorithm 1 of generating 1~7
int rand17_1()
{
int r = 0;
r += rand01();
r += rand01() << 1;
r += rand01() << 2;
if (r == 0)
return rand17_1();
else
return r;
}
//algorithm 2 of generating 1~7
int rand17_2()
{
int a;
while ((a = rand15() * 5 + rand15()) > 26) ;
return (a - 3) / 3;
}
//algorithm 3 of generating 1~7
int rand17_3()
{
int sum = 0;
for (int i = 0; i < 7; i++)
{
sum += (rand15() - 1) * pow(5, i);
}
return (sum % 7 + 1);
}
int main()
{
vector < int >ivec;
ivec.resize(100000);

cout << 'algorithm 1:' << endl;
for (int i = 0; i < 100000; ++i)
ivec[i] = rand17_1();
for (int i = 1; i <= 7; ++i)
cout << i << ' counts: ' << count(ivec.begin(), ivec.end(), i) << endl;

cout << 'algorithm 2:' << endl;
for (int i = 0; i < 100000; ++i)
ivec[i] = rand17_2();
for (int i = 1; i <= 7; ++i)
cout << i << ' counts: ' << count(ivec.begin(), ivec.end(), i) << endl;

cout << 'algorithm 3:' << endl;
for (int i = 0; i < 100000; ++i)
ivec[i] = rand17_2();
for (int i = 1; i <= 7; ++i)
cout << i << ' counts: ' << count(ivec.begin(), ivec.end(), i) << endl;
return 0;
}
算法1的思路
比如产生7的过程如下:
r = 1;
r = 1+2;
r = 3+4;
该算法来自:http://blog.sina.cn/dpool/blog/s/blog_9ce5a1b50101ae1z.html?vt=4
算法二的思路
1. 通过 rand5()*5+rand5() 产生 6 7 8 9 10 11 …… 26,27 28 29 30 这25个数,每个数的出现机率相等;
2. 只需要前面 3*7 个数,所以舍弃后面的4个数;
3. 将 6 7 8 转化为 1,9 10 11 转化为 2,……,24 25 26 转化为 7。公式是 (a-3)/3;
该算法来自:http://bbs.chinaunix.net/archiver/tid-1740087.html?page=1
另外,关于该算法的延伸思考:
这种思想是基于,rand()产生[0,N-1],把rand()视为N进制的一位数产生器,那么可以使用rand()*N+rand()来产生2位的N进制数,以此类推,可以产生3位,4位,5位...的N进制数。这种按构造N进制数的方式生成的随机数,必定能保证随机,而相反,借助其他方式来使用rand()产生随机数(如 rand5() + rand()%3 )都是不能保证概率平均的。
此题中N为5,因此可以使用rand5()*5+rand5()来产生2位的5进制数,范围就是6到30。再去掉27-30,剩余的除3,以此作为rand7()的产生器。
该段思考来自于:http://blog.csdn.net/xwdpepsi/article/details/8092860
算法三的思路
不明思路,看代码去吧。
来自:和算法二同一出处。

三种算法的随机效果PK
产生1-5的随机函数,生成随机数1-7
100000 / 7 = 14285.7
可见算法3的波动范围最小。

我的更多文章

下载客户端阅读体验更佳

APP专享