“嘟……嘟……嘟……”,第 2024 号实验区突然警铃大作、声声刺耳,应急防御系统被触发启动。

相关调查人员被秘密集中到了作战指挥室,乌克博士正在做着紧急会议说明……


乌克博士,桃花源计划 2024 区负责人,通过他的描述,众人才得知 2024 区刚刚发生了前所未有的异常状况。

这个 2024 号实验区与地球的普通城市一样,目前居住生活着一千万智能人。

作为人类向星辰大海进发,寻找宜居星球的关键一环,这个实验区发挥着举足轻重、不可替代的作用。


然而数年来一向运转正常的模拟系统却偏偏在几天前出了问题,最初监测系统就敏锐地捕捉到了部分数据异常。

然而短短的数十小时后,竟然引发了海啸般指数级的异常。

在模拟环境中的节假日时间段内,本该熙熙攘攘、人山人海的商业街道却稀稀拉拉、零零散散,显得一派萧条景象!


显然这很不正常,有人当场质疑乌克博士是不是动了祖传代码。

面对这类夹枪带棒的嘲讽言语,乌克博士并没有当回事。

他只是略带严肃地回答:“我们经过了严格测算,调查结论是随机数发生器出现了重大故障!”

“是的,先生们!正如你们眼前看到的一切,正是第 2024 号实验区的随机计算参数出了大问题而引发的连锁反应!”

乌克博士向在座的调查员们表示,会在最短时间内修复此类问题,消除隐患。


那么乌克博士提到的随机数是什么呢?

它怎么就会发生故障呢?

接下来我们就带着这几个问题一起揭秘吧!


什么是随机数?

一般人的理解,顾名思义,就是没有规律的数字呗!

这么想并没有错,随机数在计算机应用中使用的比较广泛,最为熟知的便是在密码学中的应用。

但是严格来谟,随机数应该要具备3个特性:

随机性:不存在统计学偏差,是完全杂乱的数列

不可预测性:不能从过去的数列推测出下一个出现的数

不可重现性:除非将数列本身保存下来,否则不能重现相同的数列


嗯,道理我懂,随机数就是随机一个数,但是它能出啥问题呢?

其实随机数并不简单,它的问题就出在它是真的,还是假的!

什么?它还能有假?

是的,而且我们计算机中一般都是假的随机数,被称为伪随机数!

如果用上了伪随机数,那么就有可能出现前文所说的异常情况。

是不是刷新了你的三观?


目前学界划分真伪随机数的方式非常简单,一句话就能说明白,凡是用一定的算法使用程序生成的都是伪随机数,而通过物理现象产生的随机数才是真随机数。

真假随机数之间的最大差别在哪里?

其实就在是否可以预测上

计算机算法得出的各种随机数之所以是伪随机数是因为它们的结果都是可以预测的!

只要我们知道算法和起始状态以及各种参数,就可以预测下一次随机出来的结果。

而真随机数则无法预测,就是纯粹随机的。

因此我们也可以得出一个结论,就是只有用自然的物理现象才能产生出真随机数,除此之外绝无可能为真。


既然计算机用固定算法产生的是伪随机数,那么我们就来测试测试。

使用 VB6 来生成伪随机数,通过 Rnd 函数生成 01 之间的随机数。


比如,如果想生成 110 之间的随机数,那么应该这样写。

Int(Rnd * 9) + 1
 


如果想生成 1100 之间的随机数,那么应该这样。

Int(Rnd * 90) + 10
 


可以看到产生了一组数字。


但是为啥无论怎么运行程序,产生的这些数字都是一样的呢?


原因很简单,因为它没有使用随机种子。

在使用 Rnd 之前,需要加上 Randomize 作为随机种子。

Randomize [number]
 


通常这个 number 是以系统时间为初始化基准,也就是像下面这个样子。

Randomize Timer
 


简写就是这个样子,不带任何参数即可。

Randomize
 


所谓随机种子,就是一个随机数产生前的初始起点,可以理解为,起点不一样,产生的结果自然就不一样了。

当然它也应该是某个真随机数(种子),比如当前的系统时间。

这个系统时间肯定每次都是不同的,然后以它为初始条件,在此基础上运用一些算法再产生随机数,这样就可以保证随机数(至少)看上去是随机的。

(当然这里还是要提醒一下,种子虽然不同,但并不保证结果就都不一样,原因就是算法是固定的,这个问题无解。)


现在可以做到产生的随机数是不一样的了。


完整代码如下,小伙伴们可以自行测试。

Randomize
For i = 1 To 10
    a = Int(Rnd * 90) + 10
    Label1.Caption = Label1.Caption & " " & a
Next i
 


其实就算换其他编程语言,效果也是一样一样的。

比如用 JavaScript 写一个随机数。

<script>
alert(Math.random())
</script>
 


将以上代码保存为 .html 后缀的文件,然后在浏览器上打开它。

每次刷新都会得到一个不同的 01 的随机数。


说到这儿,有的小伙伴可能有疑问,我看数字都挺随机的呀!

其实你只要产生足够多的数字,就会发现它们是有规律的,呈某种数学规律的分布。

那用计算机真随机数又是怎么产生的呢?

答案是,想办法用物理现象做为随机种子!


可以给小伙伴们举些例子。

现有的真随机数生成器,比如 PuTTYgen 的随机数,是让用户移动鼠标达到一定的长度,之后把鼠标的运动轨迹转化为种子。

PuTTYgenPuTTY 一同打包的程序,可以在 PuTTY 程序包中找到。)


打开 PuTTYgen 程序,点击生成 Generate 按钮。


然后在空白区域胡乱滑动鼠标,以使进度条前进,直到生成新的密钥它就会停止。


来张动图感受一下。


另外, Intel 通过电阻和振荡器来生成热噪声作为信息熵资源,Unix/Linuxdev/random/dev/urandom 采用硬件噪音生成随机数。

所以,要想生成真的随机数,是无法用任何一个纯算法实现的,都需要借助外部物理现象来实现。


虽然看上去需要借助外力,难度陡增,实现起来不是那么容易,但是还好不是说一点办法也没有的。

比如就有如下这么一个神奇的网站,从 1998 年以来就一直提供在线真随机数服务。

https://www.random.org/


它使用真实环境中的大气噪音作为基础来产生真随机数。


大气噪音,妥妥的自然界物理源信息啊!

基于此,这个网站提供了很多非常有趣的项目服务,有的免费,有的收费。

当然还有不少作为演示的示例内容,比如游戏。


从最简单的产生随机数入手,我们来把玩一下。

https://www.random.org/integers/


第一步,设定条件。

比如默认的条件:

  1. 生成 100 个随机整数
  2. 每一个整数都在 1100 之间
  3. 产生的结果按 5 列格式排列呈现


第二步,点击 Get Numbers 获取结果。

需要耐心等待,虽然时间不长,但是基于实际物理信息产生真随机数字是需要一定时间的。

看!5100 个随机整数产生了!


点击 Again! 按钮,可以重新生成一组新的随机数字。


好,我们再来玩一个,生成随机密码。

https://www.random.org/passwords/


第一步:

  1. 生成 5 组随机密码
  2. 每个密码有 12 位长
  3. 密码不包含容易混淆的字母或数字,比如数字 1 和 小写字母 l


第二步:

按下 Get Passwords 按钮获取密码。

你看,生成了 5 组密码,看上去挺随机的哈!


怎么样,好玩吧?

虽然是非常简单的应用,但是我们只能打开网站才能使用,有没有什么办法可以不打开网站,随时随地就可以用到这些功能呢?


好想法,其实 Random.org 为我们提供了丰富的接口,有些是免费的,有些则是收费的,可以直接拿来调用。

其中有一个 HTTP API 是免费的,我试用了一下,还是挺好用的。

https://www.random.org/clients/http/


比如生成随机整数,这个最简单了,举例如下。

HTTP API 接口语法:

https://www.random.org/integers/?num=[1,1e4]&amp;min=[-1e9,1e9]&amp;max=[-1e9,1e9]&amp;col=[1,1e9]&amp;base=[2|8|10|16]&format=[html|plain]&rnd=[new|id.identifier|date.iso-date]
 
  • num :生成多少个整数
  • min :最小整数
  • max :最大整数
  • col :生成随机排多少列
  • base :生成的是二进制( 2 )、八进制( 8 )、十进制( 10 )还是十六进制( 16
  • format :格式是html 还是 plain (纯文本)
  • rnd :随机形式,分为 new 新生成,id.identifier ID 号,以及 date.iso-date 日期


参数不少,还是举个例子吧。

比如我想新生成 10 个随机数,最小为 1 ,最大为 6 ,将结果以 10 进制纯文本形式排成 1 列。

代入参数,可以写成这个样子。

https://www.random.org/integers/?num=10&amp;min=1&amp;max=6&amp;col=1&amp;base=10&amp;format=plain&amp;rnd=new

 

小伙伴们可以将以上链接放到浏览器的地址栏中访问,就可以得到一组真随机数字啦!


基于此,我们就可以将它应用到自己做的程序中了。

以下是我自制的示例程序。


有三个部分。

最上面部分是用 VB 自带的 RND 来生成伪随机数,仅用于对比。

中间部分是利用Random.org 提供的 HTTP API 接口来产生真随机数。

最下面部分是通过鼠标移动坐标做为随机种子产生随机数。

程序还有改进的空间,仅做学习研究之用哈。


本文相关程序下载。

  • MathRandom.html - JS 随机数演示代码
  • puttygen.exe - PuTTY 密钥生成器
  • 网管小贾的随机数测试程序.exe

下载链接:https://www.123pan.com/s/bI7Mjv-ygAH3.html

提取码:

输入阅读密码,解锁隐藏内容...



★扫码关注公众号, 发送【001085】获取阅读密码


话说在解决了随机数发生器故障后不久乌克博士便向上级申请了休假,毕竟他已经连续工作了数月,需要放松休息。

偶然的一天他去逛附近超市,走出大门时无意间注意到门口旁的彩票点挤满了人。


“我说老兄,最近老天真怪,天天下雨,害得我手气贼差,隔三差五地只中了几次二等奖!”

“谁说不是啊!我听说马仨那小子每次都中头等奖!要知道这个月连这次他都已经中了四回了!”

“对对,我也听说了。最近怪事不少,连我隔壁的那个牛老六这两个月买的好几支股票都连续涨停,发了一笔不小的横财啊!”

彩票店老板瞥见了乌克博士,热情地招呼他也一块儿买上几注……


将技术融入生活,打造有趣之故事

网管小贾 / sysadm.cc

暂无评论

登录并提交评论

© 2020-present 网管小贾 | 微信公众号 @网管小贾
许可协议:CC-BY-NC 4.0 | 转载文章请注明作者出处及相关链接