一个伪随机数生成算法

这几天逛程序员论坛,发现了不少好帖子,增长了不少知识,现拿其中一则为例说明。

某人提出一个问题,说怎么样能生成一亿个不重复的随机数呢?

问题表述起来很简单,似乎只要弄明白什么叫随机数以及怎样用电脑生成随机数,就能解决问题了。这俩问题大多数程序员都会,我在这里再表述一番。

随机数,个人理解为一定范围内出现的毫无规律的数,比如扔一个骰子,落在桌面上时朝上的一面所表示的数就是随机数,这个数只能是从1到6这个范围内的数,但是具体是什么数,谁也不能肯定,因为它没有规律。一组不重复的随机数,对扔骰子来说就是扔出六个不一样的数来,再比如洗一次扑克牌,洗完了之后就是54张不重复的随机数。

第二个问题,怎么样用电脑生成随机数,只要调用某个语言的某个函数就行了。其实电脑是没办法生成一个真正的随机数的,因为电脑是高度有规律的机器,让它生成一个没规律的数,根本办不到。平时程序员用某个函数生成的随机数只是利用某个算法弄出来的伪随机数。看起来像,其实不是。能解决问题就行了。

回到这个帖子所描述的问题上来,生成一亿个不重复的随机数。那么最直接的算法就是每用函数生成一个数,就把它放在一个筐里,第一个数直接放到筐里,以后生成的数在放到筐里之前和筐里的每一个数比较一番,一旦发现筐里有和新生成的数一样的数时,丢掉这个新生成的数,再接着生成数。

毫无疑问,这种算法的效率是非常低的,看看其中的比较数的次数就知道了,最差的次数趋于无穷次。也就是说到后来,我几乎生成不了和以往不同的数。

当然还可以将这个算法升级为效率高得多的算法,每生成一个数,就把这个数从随机数生成器取的范围中去掉,比如我要生成10个随机数,第一次生成了一个3,我就把3从随机数的范围中去掉,第二次只从1到9这个范围内找。3对应4,4对应5……9对应10。这样就不存在比较这个环节了,然而又多出一个对应的环节,每生成一个数之后就要把剩下的数重新对应一遍,效率也不容乐观。

目前以我为代表的普通程序员的想象力也就到此为止了,想不出什么高级解决办法了,就当扔了一块砖头出来。下面就把真正的碧玉,一个数学家级程序员的算法,请出来。

我们先用另一种眼光来看不重复的随机数:加密。把一个能看懂的英文字符串打乱字母的顺序,变成不可读的,这就是加密。但是必须得有规律地打乱,字母a对应另外一个固定的字母Ax,字母b对应另外一个固定的字母Bx,以此类推,而且必须是一一对应的。那么字符串“ab……z”这26个字母对应的26个加密字母“AxBx……Zx”就可以看成是对应范围a到z的不重复的伪随机数,这就是数学家的算法的来源。

看看回帖者的原文:

可以采用32bit RSA算法

设A从2~(N-1)
C=(A EXP D)  mod N
满足如下条件:
D是素数,N是两个素数(P,Q)之积,
(D * E) mod ((P-1) * (Q-1))=1
因为:若
C=(A EXP D)mod N
有:
A=(C EXP E) mod N
所以,C与A 一一对应。
所以,对于A=2~(N-1),有不重复,无遗漏的伪随机码C。

凡是稍微扯上一点数学,尤其是高等数学的问题,我等泛泛之辈看起来就有点费劲,这里虽然文字不长,但是还得慢慢来看。

这里面RSA算法是密码学三大算法之一(RSA、MD5、DES),是一种不对称密码算法。说如果满足条件:D是素数,N是两个素数(P,Q)之积,(D * E) mod ((P-1) * (Q-1))=1,那么存在C与A(范围从2到N-1)一一对应,且C=(A EXP D)mod N。A是一个有顺序的数,C就是一个看似无规律的伪随机数。Mod运算表示求模,例如7Mod3=1。意思是7除以3余1。类似地8Mod3=2,9Mod3=0。EXP表示前面数的后面数次方,AEXPD表示A的D次方。这两个运算清楚了,其它的也就没什么困难的了,*是乘法的意思,大多数理科生都清楚。

搜了一下网络,还得加上一些条件,1,P和Q不能一样。2,e<(P-1)(Q-1)且e与(P-1)(Q-1)的最大公因数为1。

下面用一个例子来试验一下,看看这个算法有多神奇。

设N=15,P=5,Q=3,则A为2到14的数。现在要产生2到14的伪随机数。取D为3,E为3,C2=(2EXP3)mod15 = 8,

C3=(3EXP3)mod 15 = 12,

C4  = (4EXP3)mod 15= 4,

C5  = (5EXP3)mod 15= 5,

C6  = (6EXP3)mod 15= 6,

C7  = (7EXP3)mod 15= 13,

C8  = (8EXP3)mod 15= 2,

C9  = (9EXP3)mod 15= 9,

C10  = (10EXP3)mod 15= 10,

C11  = (11EXP3)mod 15= 11,

C12  = (12EXP3)mod 15= 3,

C13  = (13EXP3)mod 15= 7,

C14  = (14EXP3)mod 15= 14。

比较完美。如果数再大一点,可能看起来更随机一些。

由这个算法产生的1亿的伪随机数,效率那可是相当的高,只不过运算时要用到大数运算库。在一些讲求效率的场合应用的话,再做一些对应上的处理,升级一下算法,那定是相当的完美。

由此可以看出,算法的优化,如果仅仅停留在大脑能够想象到的小学数学的阶段,那是远远达不到要求的。一个优秀的程序员,还需要加深对离散数学的理解,虽然,这次提到的算法已经深入到了数论的层次上了,但是RSA算法已经是应用非常广泛的算法了,对其稍加变通,便可以发挥出更加不可思议的作用。程序员还是需要多学习算法,多学习数学,才能发挥出超出一般程序员的不可思议的能力。

一个伪随机数生成算法相关推荐

  1. JAVA梅森旋转随机算法_伪随机数生成算法-梅森旋转(Mersenne Twister/MT)

    今天主要是来研究梅森旋转算法,它是用来产生伪随机数的,实际上产生伪随机数的方法有很多种,比如线性同余法, 平方取中法等等.但是这些方法产生的随机数质量往往不是很高,而今天介绍的梅森旋转算法可以产生高质 ...

  2. 分享一种高效伪随机数生成算法

    我们知道C语言提供了随机数生成,另外Qt也提供了随机数的生成. 比如C语言,生成0-19随机数,如下: srand(time(nullptr)); // 从1970-01-01 00:00:00到现在 ...

  3. php hmacsha1计算,PHP HMAC_SHA1 算法 生成算法签名

    HMAC_SHA1(Hashed Message Authentication Code, Secure Hash Algorithm)是一种安全的基于加密hash函数和共享密钥的消息认证协议. 它可 ...

  4. 迷宫生成算法和迷宫寻路算法

    迷宫生成算法和迷宫寻路算法 大学二年级的时候,作为对栈这个数据结构的复习,我制作了一个迷宫生成算法的小程序,当时反响十分好,过了几天我又用自己已经学的DirectX技术制作了DirectX版的程序.这 ...

  5. 实验三:实现一个大素数生成算法

    一.实验内容 掌进一步掌握大素数分解的一般原理和实现方法.能用间接方法实现大素数分解.用代码实现Solovay-Strassen素性测试法或Miller-Rabin素性测试法. 二.分实现一个大素数生 ...

  6. 编译原理实验报告_任意给定一个正规式 r (包括连接、或、闭包运算),根据 Thompson算法设计一个程序,生成与该正规式等价的 NFA N 。

    任意给定一个正规式 r (包括连接.或.闭包运算),根据 Thompson算法设计一个程序,生成与该正规式等价的 NFA N . 百度网盘下载 传送门 提取码:bzjn

  7. php 实现的字典序排列算法,字典序的一个生成算法

    字典序的一个生成算法. 最近在LeetCode刷题,刷到一个题,链接: https://leetcode-cn.com/problems/permutation-sequence/ 这个题要求得长度为 ...

  8. java自动红包_Java一个简单的红包生成算法

    一个简单的红包生成算法,代码如下: /** * 红包 * @param n * @param money 单位:分 * @return **/ public static double[] redPa ...

  9. 数独-- 一个高效率生成数独的算法

    关于数独,来自维基百科的玩法解释:在9×9格的大九宫格中有9个3×3格的小九宫格,并提供一定数量的数字.根据这些数字,利用逻辑和推理,在其它的空格上填入1到9的数字.每个数字在每个小九宫格内只能出现一 ...

最新文章

  1. 力邀安卓为鸿蒙效力,期末阅读题答题秘籍2
  2. Hibernate validation annonation
  3. 【学术相关】你在读博士期间明白的最深刻的道理是什么?
  4. Spring框架学习笔记(2)——IOCDI
  5. linux欢迎信息打印本机ip,Linux shell 登录显示欢迎信息或机器信息(示例代码)
  6. java vk减号_Vue入门经常使用指令
  7. 视图分割与视图间通信资料汇总!
  8. 将u盘的文件复制到虚拟机上的linux系统上面—》文件挂载(转)
  9. 神经网络 代码python_详细使用Python代码和数学构建神经网络— II
  10. 【Android面试题】准备、hr面试问题总结
  11. ubuntu linux原生微信使用体验
  12. 全志H6 Android 7.0 平台 修改横竖屏显示
  13. [W ParallelNative.cpp:212] Warning: Cannot set number of intraop threads after parallel work h
  14. 羽毛球单打比赛中谁先发球以及在哪个区域发球?
  15. linux下安装grads
  16. 解决realplay在ubuntu中没有声音且画面很卡的问题
  17. 查看dll被哪个应用程序占用
  18. python语言程序设计(MOOC 嵩天)第六章 程序整理(0225)
  19. 你值得拥有!反向代理、负载均衡实战
  20. 默认路由与浮动路由,交换机配置(笔记)

热门文章

  1. 25个技巧和诀窍可以用来提高你的app性能
  2. ArcGIS GeoEvent 使用教程(二)
  3. 绿盟于旸:让阿里安娜火箭爆炸的缓冲区溢出 linkboy语录:tk出品必是精品呵呵...
  4. 小麦苗数据库巡检脚本,支持Oracle、MySQL、SQL Server和PG等数据库
  5. excel未保存强制关闭计算机,Excel文件未保存就关闭了,怎么恢复数据?
  6. 计算机的纸牌游戏打不开啥原因,win10系统游戏纸牌打不开解决方法 - Win10专业版官网...
  7. CTO成长之路(一):优秀的程序员
  8. heic图片如何在电脑上直接打开查看使用
  9. 在ArcGIS Online中创建三维图层和网络场景(2017.9)
  10. Origin2018(汉化版)在使用科学计数法的时候如何将坐标刻度的0.0改成0