真/僞隨機數發生器類

一直想要弄一個能夠生成真隨機數的類,但因未能找到合適的真隨機因子而未能完成。前些天偶然瞭解到IA32的CPU具有一個時鐘週期計數器,能夠提供自CPU復位後至今累計的時鐘週期數。忽然覺得這個正是最易得到而又最難預測的真隨機因子。

  這裏我們不討論嚴格意義上的“真隨機”數,以免陷入無盡的口水裏。我認爲由於系統運行狀況的不確定性,實際上連總是以固定間隔獲取時鐘計數都很難做到。再加上多核處理器各核心的負載變化、睿頻功能的狀態變更、CPU流水線被中斷的情況不同、CPU緩存的命中變化、操作系統的任務調度、真正隨機的外界事件干擾(比如鍵盤/鼠標操作,網絡通信變化等等)......如此多的變數影響下,我們獲得的時鐘計數完全無法預測。用它做真隨機因子的隨機數算法就已經是真正的隨機數了。至少,對於日常的需求而言已經可以得到滿足了。

  和通常使用的系統時間毫秒數相比較,這個時鐘週期計數更爲多變。系統時間一毫秒才改變一次,足夠一個快速的隨機數發生器產生超過十萬個隨機數了。因爲期間系統時間沒有改變,用它生成的隨機數其實還是一個固定序列。而時鐘計數則能保證每次調用都不相同,生成一個隨機數的時間至少要經過幾十個時鐘週期了。使用它來生成隨機數能保證不會出現固定序列的現象。

  另一個好處是運行效率很高。系統時間的獲取需要調用操作系統API,費時費力。而時鐘計數則僅需幾條彙編命令就能取到,輕巧容易。

  網上曾有人直接把時鐘週期計數的低位作爲隨機數來使用,但我認爲這還是不妥。畢竟該數字重複一次的週期太長了點,在此期間用戶獲得的就是一個雖然間距隨機但卻一直在不斷增大的數字序列,怎麼看都不像是一個隨機數。所以,我把他作爲隨機因子添加到線性同餘法隨機數發生器的算法裏,使得到的數字序列成爲真正無規律的真隨機序列。

  這個算法的運行效率還是非常高的,不帶參數時大約能在幾納秒的時間裏生成一個真隨機數。帶上參數後63位算法的速度下降很多,大約需要15納秒才能生成一個。原因是它需要做128位乘法運算來整理返回值。我最初用浮點數來做返回值整理,速度更快,但發現計算誤差太可惡了:用n做參數本該生成0到n-1的數值,結果調試中改置極限參數後竟然在輸出裏看到了n。於是改用內聯彙編來做整理運算。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章