淺談隨機數發生器
今 天在微博上到一篇如何使用隨機數的文章,讓我回憶起剛上大一時學C語言時,書后有道調用rand()函數的練習題,當時覺得好神奇,想知道它是怎么實現 的,大二時候學Java又遇到了random()函數,恰巧當時上機課我有機會問老師,遺憾的是老師只是告訴我那是偽隨機數,課后查查資料才了解。如今來 一篇關於隨機數發生器博文來回憶一下神奇的隨機數。
眾所周知,我們平時所使用的無論什么編程語言都會提供一個隨機數函數,而且它是偽隨機數(Pseudo Random Number),它是由算法計算得出的,是可以預測的,也就是說當隨機種子相同時,對於同一個隨機函數,得出的隨機數列是固定不變的,亞裔唯一圖靈獎得主姚期智就是研究的就是偽隨機數生成論;與之對應的就是真隨機數(True Random Number)它是真正的隨機數,無法預測且無周期性;還有一種是產生隨機數的發生器是密碼學偽隨機數發生器(Cryptographically Secure Pseudo-Random Number Generator)常用的算法有 MD5 ,SHA1 等標准, 這里不做過多討論,說說最基本的前兩種:
一、真隨機數發生器
像無法實現永動機一樣,想要實現真隨機數靠程序是永遠無法實現的,很多情況下只能看老天的眼色,比如布朗運動,量子效應,放射性衰變等。第一個真隨機數發生器是1955年由Rand公司創造的,而在1999年,intel發布Intel810芯片組時,就配備了硬件隨機數發生器,基於IntelRNG的真隨機數生成器可以生成滿足獨立性和分布均勻性的真隨機數,目前大部分芯片廠商都集成了硬件隨機數發生器,只要安裝相應驅動,了解讀取寄存器地址,可以直接調用發生器。Intel810RNG的原理大概是:利用熱噪聲(是由導體中電子的熱震動引起的)放大后,影響一個由電壓控制的振盪器,通過另一個高頻振盪器來收集數據。TRNG的類型主要有:
1.基於電路的TRNG:
i.振盪器采樣:就是上述Intel采用的方式。
ii.直接放大電路噪聲:利用電路中各種噪聲,如上述的熱噪聲作為隨機源,由於強度小,所以先要對其放大,然后對一定時間內超過閾值的數據進行統計,這樣就產生的隨機數。.
iii.電路亞穩態:亞穩態表示觸發器無法在規定時間內達到一個可確認狀態,一定條件下,觸發器達到兩個穩態的幾率為50%,所以先使電路進入亞穩態,之后根據狀態轉化為隨機數。
iv.混沌電路:不可預測,對初始條件的敏感的依賴性。以及混沌電路在芯片中易於實現的特點,可以產生效果不錯的隨機數。
2.基於其他物理源的TRNG
如宇宙射線,粒子衰變,空氣噪聲等作為隨機源,來產生隨機數。
3.其他物理信息TRNG
人為可以產生隨機數嗎?當然能!聽說一個HR拆選簡歷的方式是往天上一扔,掉在桌子上的簡歷就通過,這個HR確認懂隨機啊,而且是真隨機。這類隨機生活中隨處可見,擲骰子,抓麻將,或者統計一個月內帝都PM2.5的數值。
對於真隨機發生器我個人認為未來是可以通過生物計算機來獲取的。
二、偽隨機數發生器
通 過程序得到的隨機數無論什么算法都一定是通過遞推公式得到的序列,這本身就違反了隨機的定義,所以它們都不是真正的隨機數。偽隨機數中一個很重要的概念就 是“種子”,種子決定了隨機數的固定序列,例如在C語言rand函數得到的序列每次都是相同的,如果想得到不同序列需要調用srand設置種子;同理在 Java中 new Random(1)的構造函數參數來設置種子。下面介紹生成PRNG的幾種常見方法:
1.取中法:
i.平方取中法:
這個方法是由馮·諾伊曼在1946年提出的,思想很簡單:
- public class CustomRandom {
- static final int FIGURES = 10000;
- static long mRandom;
- public static void main(String[] args) {
- long seed = System.currentTimeMillis();
- mRandom = seed % FIGURES;
- for (int i = 0; i < 10; i++)
- System.out.println(getRandom(seed));
- }
- private static long getRandom(long seed) {
- return mRandom = (mRandom * mRandom / (long) Math.pow(10, 5/2)) % FIGURES;
- }
- }
ii:常數取中法
iii:乘法取中法:
2.同余法
- public class CustomRandom {
- static final int A = 3;
- static final int M = (1 << 31) - 1 ;
- private static long mRandom;
- public static void main(String[] args) {
- mRandom = System.currentTimeMillis() / Integer.MAX_VALUE;
- for (int i = 0; i < 10; i++) {
- mRandom = (mRandom * A) % M;
- System.out.println(mRandom);
- }
- }
- }
- public class CustomRandom {
- static final int N = 5;
- static long mRandom;
- public static void main(String[] args) {
- long mRandom = System.currentTimeMillis();
- for (int i = 0; i < 10; i++) {
- mRandom = Math.abs((mRandom >> N) + (mRandom << N));
- System.out.println(mRandom);
- }
- }
- }
4.梅森旋轉算法

下面的一段偽代碼使用MT19937算法生成范圍在[0, 232 − 1]的均勻分布的32位整數
- <span style="font-size:10px;"> //創建一個長度為624的數組來存儲發生器的狀態</span>
- int[0..623] MT
- int index = 0
- //用一個種子初始化發生器
- function initialize_generator(int seed) {
- i := 0
- MT[0] := seed
- for i from 1 to 623 { // 遍歷剩下的每個元素
- MT[i] := last 32 bits of(1812433253 * (MT[i-1] xor (right shift by 30 bits(MT[i-1]))) + i) // 0x6c078965
- }
- }
- // Extract a tempered pseudorandom number based on the index-th value,
- // calling generate_numbers() every 624 numbers
- function extract_number() {
- if index == 0 {
- generate_numbers()
- }
- int y := MT[index]
- y := y xor (right shift by 11 bits(y))
- y := y xor (left shift by 7 bits(y) and (2636928640)) // 0x9d2c5680
- y := y xor (left shift by 15 bits(y) and (4022730752)) // 0xefc60000
- y := y xor (right shift by 18 bits(y))
- index := (index + 1) mod 624
- return y
- }
- // Generate an array of 624 untempered numbers
- function generate_numbers() {
- for i from 0 to 623 {
- int y := (MT[i] & 0x80000000) // bit 31 (32nd bit) of MT[i]
- + (MT[(i+1) mod 624] & 0x7fffffff) // bits 0-30 (first 31 bits) of MT[...]
- MT[i] := MT[(i + 397) mod 624] xor (right shift by 1 bit(y))
- if (y mod 2) != 0 { // y is odd
- MT[i] := MT[i] xor (2567483615) // 0x9908b0df
- }
- }
- }
==================================================================================================
轉載自nash_ :http://blog.csdn.net/zmazon/article/details/17383521
===================================================================================================