引出
在現實中, 會有拋硬幣猜正反的操作, 硬幣要麼是正, 要麼是反, 在揭曉之前, 我們誰也不知道它現在的狀態. 而這, 是因爲其中存在着很大的不確定因素, 如拋硬幣的力度、拋硬幣的角度、接硬幣的力度和角度、硬幣的重量、當前風速等等.
但是在計算機中, 要想生成一個隨機數, 就需要通過一個算法來實現, 那麼生成隨機數的算法是如何實現的呢? 簡單想一下這個事情, 通過確定的輸入, 確定的步驟, 輸出不確定的值? 這還是計算機乾的事情嗎?
當然不是, 所以一直都在說函數生成的是僞隨機數
而不是真正的隨機數. 僞隨機數
是什麼呢? 我理解的就是, 雖然生成的數不是隨機的, 但是在進行概率統計時是均勻分佈的, 雖然數字不是真正隨機的, 但是可以滿足日常使用就夠了.
在計算機中生成隨機數, 肯定要告訴它具體的操作步驟, 而步驟一旦確定, 生成的結果序列就確定了, 這也是爲什麼在調用隨機數生成函數的時候需要設定隨機種子了, 因爲函數是固定的, 如果輸入也固定, 那結果就不會發生變化了. 這個隨機種子在實際中一般都使用當前時間戳.
所以, 現在問題就可以這樣描述了: 設定函數 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算法 等等.....
等等吧, 有很多生成隨機數的方法, 不過具體怎麼生成並實現我並不關心, 我只是想了解一下它大概是如何工作的, 能夠如何生成隨機數. 畢竟隨機函數也用了這麼久了, 稍微瞭解一下還是可以的. 上面這兩種都是不安全的隨機算法, 怎麼說呢? 就是如果知道了當前的狀態, 就可以通過計算, 得出之後所產生的隨機數. 而一些安全的隨機算法, 即使攻擊者得到了大量的隨機輸出, 也很難預測未來的輸出. 看了幾種安全的隨機算法, 都沒看太明白, 水平有限...