《大学算法教程Algorithms》笔记--Chapter1--Part3

来源:互联网 发布:网络平台 英文缩写 编辑:程序博客网 时间:2024/05/17 03:29

1.3节习题2. 用rand(1,6)来实现随机掷硬币

这个问题比较简单,就是把rand(1,6)产生的结果分类而已.

最简单的分类就是 1 2 3 当成正面, 4 5 6当成反面

稍微有点水平的分类就是 奇数当成正面 偶数当成反面, 这种分类编程上可能漂亮一些.


本章习题1.5 用rand(1,2)来实现公平的掷骰子

这也就是要求用掷硬币来实现掷骰子

一个直接的答案就是每次投掷3次硬币,规定正代表1,反代表0

三次的结果按 T1T2T3 组成一个二进制数

这个二进制的结果1-6分别代表骰子的结果,0和7忽略.


按道理这个题目应该终结了,可是作者偏偏给了一个提示,就是

要求算法可以终止还是不要求算法终止,两种情况是不同的.

这句话我的理解是:

如果算法不要求终止,就用之前的办法就可以,然后连续不断的输出随机数即可.  这种情况下,产生n个结果需要调用rand(1,2)的次数是3n.

如果要求算法终止,比如知道需要生成n个随机数,做法可以有什么不同呢?    我的理解是可以利用之前每3次投硬币丢到的2次结果.  初看起来是无法利用的,比如产生的结果是7,那代表那个数字呢?   其实是可以利用的.但是方法应该有不同.   我们举个简单的例子比如已知需要投2次骰子,其实只要能等几率产生36种可能的结果就行了.   比如

(1,1)0(1,2)1(1,3)2......(1,6)5(2,1)6(2,2)7......(6,6)35


这个表格,左边是掷骰子的结果,右边是对应起来的二进制的结果(为了方便写成十进制而已).

从右边到左边有什么规律没有?

实际上,如果将左边骰子的结果改变一下,从1-6对应到0-5,左边实际上可以认为是六进制,所以现在的算法就是把掷硬币的结果进行转换,改成六进制即可.那掷硬币的结果怎么处理呢?就是让结果反复地除以6啊.这样程序实现的问题也就解决了.


这个方法跟上面的方法的区别不仅仅在于此,最主要的区别在于利用了之前投硬币过程中无法利用的结果.

第二种方法,生成n个骰子的结果,需要投掷的硬币次数是ceil(log2(6^n)),这个结果基本上等于n*log2(6),显然优于上面的3n.








0 0
原创粉丝点击