引出
在现实中, 会有抛硬币猜正反的操作, 硬币要么是正, 要么是反, 在揭晓之前, 我们谁也不知道它现在的状态. 而这, 是因为其中存在着很大的不确定因素, 如抛硬币的力度、抛硬币的角度、接硬币的力度和角度、硬币的重量、当前风速等等.
但是在计算机中, 要想生成一个随机数, 就需要通过一个算法来实现, 那么生成随机数的算法是如何实现的呢? 简单想一下这个事情, 通过确定的输入, 确定的步骤, 输出不确定的值? 这还是计算机干的事情吗?
当然不是, 所以一直都在说函数生成的是伪随机数
而不是真正的随机数. 伪随机数
是什么呢? 我理解的就是, 虽然生成的数不是随机的, 但是在进行概率统计时是均匀分布的, 虽然数字不是真正随机的, 但是可以满足日常使用就够了.
在计算机中生成随机数, 肯定要告诉它具体的操作步骤, 而步骤一旦确定, 生成的结果序列就确定了, 这也是为什么在调用随机数生成函数的时候需要设定随机种子了, 因为函数是固定的, 如果输入也固定, 那结果就不会发生变化了. 这个随机种子在实际中一般都使用当前时间戳.
所以, 现在问题就可以这样描述了: 设定函数 f(x), 结果为[a, b, c, d…]. 其结果序列在随机区间均匀分布.
那么如何生成这个函数呢? 简单看了几种随机函数, 主要了解一下思想, 毕竟咱也不会真正的去写一个这样的函数.
计算机中的伪随机数
平方取中
由伟大的冯诺依曼前辈想出的. 其随机序列生成如下:
- 接收四位数输入 x
- s=x^2
- 若 s 不足8位, 左侧补0
- 取 s 的中间4位作为随机数y
- 将y 作为输入, 回到步骤1, 生成下一个随机数
是不是感觉很简单, 这样都能生成随机数? 为啥我没想到. 而且, 这样生成的数字符合统计学的均匀分布吗? 别说, 我还真写了一个小脚本, 跑了一下, 生成了一亿条数据, 只把生成的四位数字判断了一下. 结果其均匀分布效果不怎么样.
线性同余
其函数描述很简单: f(x)=(ax + b) % m. 随机序列的生成同理, 将上一次的输出作为下一次的输入. 很明显, 其中的 m 决定了序列生成随机数的最大值, 截断性线性同余法, 逆同余法 等是它的变种.
其他
还有线性反馈移位寄存器法、滞后斐波纳契法、马特塞特旋转法、WELL算法 等等…..
等等吧, 有很多生成随机数的方法, 不过具体怎么生成并实现我并不关心, 我只是想了解一下它大概是如何工作的, 能够如何生成随机数. 毕竟随机函数也用了这么久了, 稍微了解一下还是可以的. 上面这两种都是不安全的随机算法, 怎么说呢? 就是如果知道了当前的状态, 就可以通过计算, 得出之后所产生的随机数. 而一些安全的随机算法, 即使攻击者得到了大量的随机输出, 也很难预测未来的输出. 看了几种安全的随机算法, 都没看太明白, 水平有限…