题目是从CU上看到的,我的算法是:
int rand7()
{
    int a;
    while( (a=rand5()*5+rand5()) > 26 );
    return (a-3)/3;
}
可惜没办法验证,不知道这个算法是否正确?(问题一)。
(验证方法是通过双循环将两个rand5()分别换成1 2 3 4 5,但剔除掉(5,2)(5,3)(5,4)(5,5)这四个组合)

算法思路是:
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

注:
我觉得不能将 while( (a=rand5()*5+rand5()) > 26 ) 其中一个rand5()移到while之外,即不能写成
int b = rand5();
int a;
while( (a=b*5+rand5()) > 26 ); 或 while( (a=rand5()*5+b) > 26 );
因为出现 >26 的情况,说明 b 有很大机率很大,从而又导致while之后的a有很大机率很大,破坏了平衡性。
这个备注中的看法对么?(问题二)

但,令人惋惜的是,这不是一个严格意义上的算法,因为“计算机算法”比“数学上的算法”多两个限定,是“有限时间有限步骤内……”,而while( (a=rand5()*5+rand5()) > 26 )可能会循环超过可忍耐次数,即某次运行这段代码可能到地球灭亡时还没结束,虽然几率很低,但有可能发生。

------------------------------------------------------------------------------------

google了一下,找到另一种方法:(本质和上面的算法相同,但要使得第二步不产生多余的数)
找到一个五进制的数 444…4,这个数正好能被7整除
于是他找到444444(五进制)这个数,也就是15624
产生nnnnnn(五进制)的方法很简单,就是每位都通过rand5-1来产生
然后将nnnnnn%7+1就得到了均匀分布于1到7的算法。

这个算法是错误的,因为444444(五进制)内包含有15625个数,不是15624个数,前者不是7的整数倍。
用我的变形算法来描述就是:
通 过 r*5^0 + r*5^1 + r*5^2 + r*5^3 + r*5^4 + r*5^5 产生 3906 到 19530 共15625个数的均匀分布,可惜15625不是7的整数倍,还是需要舍弃掉最后一位。作者错误在于马虎的认为 0至n 内有n个数,其实是n+1个数。

虽然作者的结果是错误的,但思路是正确的,只要能找到一个数n,使得 4 + 4*5 + 4*25 + 4*125 + 4*625 + 4*3125 + …… 的结果加一后是7的整数倍。
我用代码暴力求解,在数据溢出之前都没找到这个数。于是从理论上分析,444…4(五进制)+1 也就是 5的x次方,永远不可能是7的倍数。

还google到其它一些巧妙的算法,但可惜作者并没有真正理解“随机”的概念。

------------------------------------------------------------------------------------

思考一下 rand5()+rand5(),将产生 1/25个2,2/25个3,3/25个4,4/25个5,5/25个6,4/25个7,3/25个8,2/25个9,1/25个10。
如果能找到一个公式,使之产生一系列不同几率的数,将这些数分成7组,使得每组数的几率总和为1/7就可以了。
假设这个公式f需要n个rand5()为自变量,则最多产生5^n个数,不是“最多”的情况说明不同参数组合产生了相同的数,无论是不是“最多”的情况,都可以证明每个数的几率都必然是 1/(5^n) 的整数倍。
那么无论怎么分组,每组数的几率总和都应该是 m * 1/(5^n)。
求 m/(5^n) = 1/7 的整数解,即求 5^n = 7m 的整数解,很显然是无解的。(前者的个位数是5,而后者的个位数不可能是5)

从理论上来证明:
无论是多么复杂,多么稀奇古怪的公式,n个自变量将产生一个n维度的空间。如果产生了低于n维度的空间,那说明其还是n维度,但某些维度被压缩成了零。
因为rand5()在每个维度上只有5个“自由度”,因此这个空间只有5*5*5……=5^n个点。
即:任意一个含有n个自由度为5的自变量的公式,无论多么稀奇古怪,都将产生5^n个值,虽然某些值可能相同。(这其实很显然,根本不需要上面用n维空间来说明)
5^n 不可能是 7 的倍数。(前者的个位数是5,而后者的个位数不可能是5)

自此证明这个问题是无解的。

m/(5^n)=1/7这个推导出来的数学公式和本文一开始的算法非常的匹配,就像一对同卵孪生姐妹^_^,可以互相印证。

------------------------------------------------------------------------------------

还有一位说话很冲的仁兄,给出了一个自谓“总体随机”的算法。他的算法是什么不重要,因为根本不存在这种算法,他将“等概率”误当成了“总体随机”。
所谓“总体随机”是指在一个大的分组上实现了“随机”,在大分组上可能是等概率1/7随机吗?
我将他,及他们,的算法化简得更“雷”人一点就是
int rand7() { 依次循环返回 1 2 3 4 5 6 7 }
这是等概率的,但不“随机”,当然也可以说它是个“伪随机”算法,但规律性这么明显,只能算是个暴烂的伪随机算法。
(BTW,数字计算机经由软件产生的随机算法,其实都是有规律的,所以都不是真实的随机算法,只是它们的规律太复杂,复杂到需要收集足够多的序列集,才可以推断出下一个值。但要知道无论多么复杂,在本质上都不比{ 依次循环返回 1 2 3 4 5 6 7 }更高级。)
因此,部分人对这道题给出的算法其本质都是 自己写了个自认为还可以接受的伪随机算法混杂着真随机的rand5(),便自以为是真随机了。

转载于:https://www.cnblogs.com/waka401/archive/2012/08/07/2627356.html

已知一个函数f可以等概率的得到1-5间的随机数,问怎么等概率的得到1-7的随机数...相关推荐

  1. html如何获得网址,已知一个网址,如何获得该网址对应的html源代码?在del 找人事管理软件...

    销售管理软件版1楼: 已知一个网址,如何获得该网址对应的html源代码?在delphi中如何实现?今天不解决,没饭吃了... 2楼: 用WebBrowser控件,先把网址传给WebBrowser,然后 ...

  2. /*已知一个排好序的数组,按数组原排序方式插入一个数据*/

    /*已知一个排好序的数组,按数组原排序方式插入一个数据*/std::vector<int>shuzu = {1,2,3,4,5,7,8,9};int x = 0, caru = 6;std ...

  3. matlab二维图形中确定一点的坐标系,在CAD中已知一个平面图中两个点的坐标如何建立坐标系以便求出图形中任一点的坐标?...

    在CAD中已知一个平面图中两个点的坐标如何建立坐标系以便求出图形中任一点的坐标?以下文字资料是由(历史新知网www.lishixinzhi.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一 ...

  4. SAP HUM已知一个内部HU号码,如何得到HU号码?

    SAP HUM已知一个内部HU号码,如何得到HU号码? 去表VEPO 查数据即可, 为什么HU要有internal HU号码 ? Prior to the existence of HUM, in W ...

  5. c#中已知一个外部窗口的句柄,怎么关闭

    已知一个外部窗口的句柄,怎么关闭它.怎么给这个窗口的一个文本框设置内容. --------------------------------------------------------------- ...

  6. 已知一个掺杂了多个数字字符的中文名拼音,去掉所有数字字符之后,形式为“名”+空格+“姓”;并且名和姓的首字母大写,其他小写,要求输出姓名全拼,且全为小写。(后附详细样例说明)

    已知一个掺杂了多个数字字符的中文名拼音,去掉所有数字字符之后,形式为"名"+空格+"姓":并且名和姓的首字母大写,其他小写,要求输出姓名全拼,且全为小写.(后附 ...

  7. 每日一题(42)—— 已知一个数组table,用一个宏定义,求出数据的元素个数

    已知一个数组table,用一个宏定义,求出数据的元素个数. // 总大小除以第一个元素的大小 #define TNTBL (sizeof(table)/sizeof(table[0]))

  8. python求近似值_python 已知一个字符,在一个list中找出近似值或相似值实现模糊匹配...

    已知一个元素,在一个list中找出相似的元素 使用场景: 已知一个其它来源的字符串, 它有可能是不完全与我数据库中相应的字符串匹配的,因此,我需要将其转为适合我数据库中的字符串 使用场景太绕了, 直接 ...

  9. java正方形矩阵_已知一个NxN的矩阵A,求矩阵中所有边长为m的正方形的子矩阵

    已知一个NxN的矩阵A,求矩阵中所有边长为m的正方形的子矩阵内元素的中位数.(m 例子: // m = 3 n = 5 // 01234 ݂         //  0 11357 ݂         ...

最新文章

  1. 从*p++说指针,数组,结构和函数
  2. 【青少年编程】黄羽恒:漫天飞雪
  3. 网络传输数据格式的选择
  4. Leangoo Talk第一期——Scrum与OKR融合实践
  5. leetcode 2. 两数相加
  6. 表设计避免使用保留字
  7. rtmp测试地址_超详细搭建多码率测试环境(成为流媒体高手必经之路)
  8. Java2Days 2012:Java EE
  9. oracle utl inaddr,oracle11g之ACL拙见
  10. win7(64位)php5.5-Apache2.4-mysql5.6环境安装
  11. 【转载保存】Java+Selenium使用
  12. java输入一串字符串反转_反转Java中的字符串
  13. 前后端分离实现文件下载功能
  14. 电脑控制android手机神器,scrcpy
  15. x,y,w,h与xmin,ymin,xmax,ymax的关系
  16. 用数据说话:刘强东制造“负熵增”
  17. ORA-00392 ORA-00312 错误处理
  18. java去除水印_易剪辑,分享一款免费的去除水印的工具
  19. java怎么获取索引值,Java 实例 - 获取向量元素的索引值
  20. FastReport的使用方法

热门文章

  1. OpenGL环境配置(超全整合版)
  2. 数据库完整型概念与完整性约束
  3. bzoj 3380: [Usaco2004 Open]Cave Cows 1 洞穴里的牛之一(状压+BFS)
  4. C语言实现链队列并测试
  5. k8s安装部署Istio
  6. 汇编三星题:已知数组A包含20个互不相等的字型整数,数组B包含30个互不相等的字型整数,试编制一程序把在A中而不在B中出现的整数放于数组C中。
  7. P4171 [JSOI2010]满汉全席
  8. Codeforces976D Degree Set 【构造】
  9. Android学习之Android 5.0分享动画实现微信点击全屏效果
  10. HihoCoder 1527 动态规划,贪心