`
dowhathowtodo
  • 浏览: 777341 次
文章分类
社区版块
存档分类
最新评论

如何用随机函数rand5来构造随机函数rand7 一道经典的算法题

 
阅读更多

试一下以对话的方式写博~如果看不到人物头像,请刷新页面获取最新的CSS。如果有建议或意见,欢迎到我的微博上跟帖~这里是腾讯微博这里是新浪微博

常规方法

  • 今天公司有一个面试题是这样的:假如有一个函数rand5能等概率生成1 - 5 之间的整数,如何利用rand5来实现rand7?rand7函数的要求是能够等概率生成1 - 7之间的整数。说实话我自己也不是很清楚。
  • 这个问题很经典的。carreercup那本书上有个常见的解法,我记得算法大概是这样的,用PHP写写吧:
01 echo'rand7 = '.rand7();
02
03 functionrand7()
04 {
05 while(true)
06 {
07 //得出[0,24]的平均分布
08 $i= 5 * (rand5() - 1) + (rand5() - 1);
09 //只取前21个, 前21个也是平均分布,然后mod 7
10 if($i< 21 )
11 {
12 return$i% 7 + 1;
13 }
14 }
15 }
  • 这么写是什么意思呢?
  • 两次使用rand5(),可以生成1-25的所有数。5 * (rand5() - 1) 可以生成 0 - 20,而后面的则可以生成0 - 4。用数学表达的话就是 [0, 24]。
  • [0, 24] 范围内生成的随机数$i如果大于21,就用 while (true) 重新生成。当$i < 21的时候,就可以用模运算了。
  • 明白了。当 $i < 21的时候,模 7 的结果是 0-6,加1就可以修正为 1-7,这样就可以通过rand5来实现rand7了。

算法的一些释疑

  • 话说得出[0,24]的平均分布的 $i = 5 * (rand5() - 1) + (rand5() - 1); 为什么要这么写呢?为什么不能直接 $i = 6 * (rand5() - 1) ?
  • rand5()产生的是[1,5]的均匀分布,但是有没有发现最后产生的rand7()却是[0,6]的,那么平均分布是如何实现的呢?
  • 5*(rand5()-1) 生成的是 0, 5,10,15,20各20%的概率,rand5()-1 是0,1,2,3,4各20%概率,两者相加,就是0-24各1/25的概率,这样就保证了平均分布的问题了。基本的概率和排列组合问题了。
  • 前21个也是平均分布,那么我取 $i < 14 也可以么?这样也能保证平均分布吗?
  • 应该也可以,但是增加了可能的循环次数。你看到 while (true) 这行代码吗?当while里面的条件不满足,循环就会一直下去。所以从程序上考虑,就是用了21而非14吧。

晚些时候

  • 我Google了下,貌似还有其它思路。先用2个rand5产生rand10(注意,不是相加),然后从rand10产生rand7。
01 // Gen 0, 1 equal probability
02 intrand01()
03 {
04 inti = rand5();
05 while(i > 4) {i = rand5();}
06 returni % 2;
07 }
08
09 // Gen 0, 1, 2, 3, 4, 5, 6, 7 equal probability
10 intrand07()
11 {
12 returnrand01() << 2 + rand01() << 1 + rand01();
13 }
14
15 // Gen 1, 2, 3, 4, 5, 6, 7 equal probability
16 intrand7()
17 {
18 inti = rand07();
19 while(i == 0) {i = rand07();}
20 returni;
21 }
  • 还有一种方法,可以直接把概率问题转化到矩阵中解决。
01 intmatrix[5][5];
02
03 memset(matrix, 0,sizeof(matrix));
04
05 // Set matrix with num 1-7, each num has the same count.
06 for(inti = 1; i <= 7; ++i)
07 {
08 for(intj = 0; j < 3; ++j)
09 {
10 *matrix++ = i;
11 }
12 }
13
14 intrand7()
15 {
16 inti;
17
18 do
19 {
20 i = matrix[rand5() - 1][rand5() - 1];
21 }while(i == 0);
22
23 returni;
24 }
  • 你还真好学。。

通过这个面试题学到了等概率问题的各种解法,可以从把数从二进制角度看,可以用公式拼接出更大的等概率值域空间,也可以直接把概率问题转化到矩阵中解决。

rand5() 它能够等概率生成 1-5 之间的整数。所谓等概率就是1,2,3,4,5 生产的概率均为 0.2 。现在利用rand5(), 构造一个能够等概率生成 1- 7 的方法。 这里有两个特别重要的点,一是 如果 rand5() + rand5(), 我们能够产生一个均匀分布的 1 - 10 吗? 答案是否定的。比如对于 6来讲(4+2, 2+4, 3+3),它被生成的生成的概率比1 (1+0,0+1)要大。

第二个点就是我们不可能用rand5()直接产生 1- 7 的数,不管你用加减乘除都不行。所以,我们要构造一个更大的范围,使得范围里每一个值被生成的概率是一样的,而且这个范围是7的倍数。

先产生一个均匀分布的 0, 5, 10, 15, 20的数,再产生一个均匀分布的 0, 1, 2, 3, 4 的数。相加以后,会产生一个 0到24的数,而且每个数(除0外)生成的概率是一样的。我们只取 1 - 21 这一段,和7 取余以后+1就能得到完全均匀分布的1-7的随机数了。

转自:http://www.nowamagic.net/librarys/veda/detail/2172

分享到:
评论

相关推荐

    -C++参考大全(第四版) (2010 年度畅销榜

    7.9 用sizeof来保证可移植性 7.10 typedef 第8章 C风格的控制台I/O 8.1 一个重要的应用说明 8.2 读写字符 8.3 读写字符串 8.4 格式化的控制台I/O 8.5 printf() 8.6 scanf() 第9章 文件I/O 9.1 C与C++的文件I/O 9.2...

    改进版贪吃蛇

    ①用构造函数构造贪吃蛇 snake(int der ,int CountNode,int Speed,int FoodLife ,bool Snake_life,int choise); //snake类的构造函数 snake::snake(int der ,int CountNode,int Speed,int FoodLife ,bool Snake_life...

    并行计算课程设计(代码+执行文件+文档)

    使用CreateThread()函数创建线程,用WaitForMultipleObject()函数管理线程来监测多个对象。采用SetEvent来设置事件处理线程间的同步问题。 伪代码如下: DWORD WINAPI ThreadOne(LPVOID param) { 对前一半数据进行...

    银行叫号模拟系统

    一系列的Set函数,一系列的Get函数,以及构造函数,复制函数,=的重载函数以及Reset函数 银行(bank)里面需要包含的数据: 银行中的人有两种状态,一是等待,二是接受服务,而这等待状态遵循先到先得的原则,因此,...

    c语言24点游戏(附源代码)

    首先进行四个数的随机输出(给定的范围是1到13),用rand()函数实现。 接着让用户输入,并对用户输入的进行判断,这里我用了数据结构里栈构造一个计算器对输入的进行运算。定义一个存储运算符的栈SNode_Symbol和一个...

    mysql 某字段插入随机数(插入随机数到MySQL数据库)

    常用的代码 UPDATE `表名` SET `字段名`=ceiling(rand()*500000+500000) WHERE ...步骤1:随机数的SQL函数为rand() ,而rand()生成的是0-1之间的小数。 步骤2:将rand()*10 将产生1-10之间的带小数的数字,可以使

    C++ 小型复数计算器

    CComplex(double real=0,double image=0) //构造函数 { Real=real; Image=image; } friend istream & operator&gt;&gt;(istream &is,CComplex &com); //重载输入 friend ostream & operator(ostream &os,CComplex &com); /...

    php网络开发完全手册

    4.2.8 随机函数rand与srand 66 4.3 关于引用的解释 67 4.3.1 对变量的引用 67 4.3.2 对函数的引用 68 4.3.3 引用的释放 68 4.4 小结 69 第5章 PHP中类的应用 70 5.1 PHP中OOP的应用 70 5.1.1 类简介 70 5.1.2 类的...

    操作系统实验内存管理器

    实验三 内存管理 3.1 实验简介 本实验要求构造一个没有虚存功能的内存管理系统。任务如下: • 设计一个内存管理器,支持至少两...内有函数能够返回一个范围在0和RAND_MAX之间的一个随机整数,该随 机量 服从均匀分布。

    LINGO软件的学习

    A5 2 3 9 5 7 2 6 5 41 A6 5 5 2 2 8 1 4 3 52 销量 35 37 22 32 41 32 43 38 使用LINGO软件,编制程序如下: model: !6发点8收点运输问题; sets: warehouses/wh1..wh6/: capacity; vendors/v1..v8/: demand; ...

    并行计算课程设计(报告+代码+可执行文件)

    使用CreateThread()函数创建线程,用WaitForMultipleObject()函数管理线程来监测多个对象。采用SetEvent来设置事件处理线程间的同步问题。 伪代码如下: DWORD WINAPI ThreadOne(LPVOID param) { 对前一半数据进行...

    Matlab代码大全

    matlab代码,易于查找,如 ...eye 产生单位阵 rand 产生随机分布矩阵 linspace 构造线性分布的向量 randn 产生正态分布矩阵 logspace 构造等对数分布的向量 zeros 产生零矩阵 ones 产生元素全部为1的矩阵 : 产生向量

    C++ MFC实现飞机大战游戏

    MFC类库中提供了丰富的CObList类的成员函数,此程序主要用到的成员函数如下:(1) 构造函数,为CObject指针构造一个空的列表。 (2) GetHead(),访问链表首部,返回列表中的首元素(列表不能为空)。(3) AddTail(),在...

    c# 加密和解密相关代码

    添加一个Button 控件,用来使用MD5算法对输入的数据进行加密。 (3)程序主要代码如下: public string Encrypt(string strPwd) { MD5 md5 = new MD5CryptoServiceProvider(); //创建MD5 对象 byte[] data = System....

    《你必须知道的495个C语言问题》

    3.14 如果我不使用表达式的值,那我应该用i++还是++i来做自增呢? 39 3.15 我要检查一个数是不是在另外两个数之间,为什么if(a b c)不行? 40 3.16 为什么如下的代码不对?int a=1000, b=1000; long int c=a * ...

    PT80-NEAT开发指南v1.1

    使用 NEAT 工程向导建立应用程序 ........................................................................................................ 5 编译及运行程序(模拟器下) ......................................

    打冰雹游戏源程序

    题目描述:“打冰雹”游戏是指从窗口顶部落下多个圆球表示的“冰雹”,用户使用鼠标来指引箭头表示的“枪”瞄准其中一个圆球,单击鼠标射击。如果打中圆球则加分,没打中减分。若累积有5个圆球一直未被击中而落到...

    C语言FAQ 常见问题列表

    o 4.5 我可否用括号来强制执行我所需要的计算顺序? o 4.6 可是 && 和 || 运算符呢?我看到过类似 while((c = getchar()) != EOF && c != '\n') 的代码 …… o 4.7 我怎样才能理解复杂表达式?``序列点" 是什么?...

    sparkcore.thingspeak:用于将值发送到 ThingSpeak 通道的 Spark Core 库

    构造函数需要提供通道 API 密钥。 该密钥可以从 thingspeak 网站获得,更多详细信息请。 ThingSpeakLibrary::ThingSpeak thingspeak ( " YOUR-CHANNEL-KEY " );3. 设定值将值发送到thingspeak有两个步骤。 最初必须...

    你必须知道的495个C语言问题

    3.14 如果我不使用表达式的值,那我应该用i++还是++i来做自增呢? 3.15 我要检查一个数是不是在另外两个数之间,为什么if(abc)不行? 3.16 为什么如下的代码不对?inta=1000,b=1000;longintc=a*b; 3.17 为...

Global site tag (gtag.js) - Google Analytics