為什麼有程序員都說取的隨機數是偽隨機數?
我覺得取的數每次都不同還算好啦,比如我用lua發牌和麻將每次都不同,而不像以前的英雄無敵2每次一開始的序列都是一樣的。為什麼他們都說隨機數總是偽的沒有真的?
C系的語言是否可以以只讀方式在硬碟或內存中根據隨機生成的地址和偏移來搜索,把任意不為00或FF的值作為種子?
偽隨機數是看似隨機實質固定的周期性序列。P. S. 這和是否「高級程序員」無關。
C系的語言是否可以以只讀方式在硬碟或內存中根據隨機生成的地址和偏移來搜索,把任意不為00或FF的值作為種子?
你都已經先隨機了,還產生種子何用?
應該這麼說,只要是通過演算法產生的隨機數都是偽隨機數。通過真實隨機事件取得的隨機數才是真隨機數。Linux和windows 系統都有自帶的真隨機數函數,它們是通過外部噪音來實現的,如,敲擊鍵盤的時間間隔,特定的中斷等。想編程語言自帶的隨機數函數是很容易被黑客破解的,例如:Java的隨機數產生是通過去模運算產生的,黑客只需要知道連續的2個隨機數就可以預測下一個隨機數。python 採用的是MT演算法,破解難度要稍微比Java 難一些。推薦看下這篇博客:http://rocyblog.com/blog/detail/10/
RANDOM.ORG - True Random Number Service
這個網站提供真隨機服務,據說是根據大氣雜訊(atmospheric noise)算出來的。博彩業用的貌似蠻多的。可以用adc取物理雜訊
只要這個隨機數是由確定演算法生成的,那就是偽隨機
偽隨機數有破解的可能性,比如如果你在伺服器上面針對每個用戶的每個行為製作一個隨機數發生器,或者針對全服,但伺服器人數很少,並且隨機數發生器是某種固定演算法的,那麼這個隨機數發生器可以根據結果匹配來獲得下一次的結果。
只要在本機做出隨機數的序列,然後匹配一下就可以了,這種事是發生過的。至於種子,這就很難說了,我覺著應該不靠譜,因為這個值很可能固定在某個數字上的概率非常高。有些人是取時間毫秒數的,可能更好點。如果你種子相同,你生成的數列肯定是每次一樣的...
種子不同,不過讓你看起來覺得每次生成的數列不一樣罷了...
種子的選擇有規律嗎?肯定是有!那麼生成的隨機數也一定是有規律的了。
既然有規律,那肯定就是偽隨機了...因為你不知道種子和隨機數演算法對你來說當然就是隨機數。如果知道了種子和隨機數演算法那麼就可以推算出隨機數數列了。
因為計算機是有限狀態機
有些人說以現實雜訊作為隨機數,我只能說如果你能曉得它的分布的話還是可以用的,如果不能知道一樣是不能用的。對了,你還得確定它是平穩的。但是對於日常應用做個鬥地主發牌程序來說偽隨機已經足夠好用,真正對於隨機數有苛刻要求的是密碼學和一些科研領域,然而目前大多數使用的也是偽隨機演算法。
有人又說我們用自然雜訊作為種子行不行?但是決定隨機數"質量『的是隨機數生成演算法而不是種子,對於觀測者來說,種子是什麼並不重要。設想一下一個極端情況,隨機數生成函數f(seed) = seed%5這樣一個很弱雞的演算法,不管你的種子取的多隨機,只要偽隨機序列取的長度大於5,我就能找到規律,所以說並沒有卵用。隨機的定義是:在定義域中選擇出任何一個元素的概率相等。CS中,有兩種方法取隨機數,硬體方法和軟體方法。
硬體方法是指採集某一種物理雜訊,經過抽樣、量化之後得到的隨機數。例如大氣雜訊。此類雜訊是由自然界中的布朗運動等現象產生的,因此可以看作真正的隨機數生成器。
軟體方法是使用演算法產生隨機數,一個普遍使用的是Linear Congruential Generator:給正整數seed, A, B, N, 則有數列X[n+1] = (A*X[n] + B) mod N, X[0] = seed。該數列中的元素可看作隨機數,但不是真正的隨機數,因為它存在周期。如果係數A和B的公因數越大,該數列的周期越小,而且最大周期 = N。一般這個演算法使用兩個非常大的質數作為A和B,一個很大的自然數作為N。Borland C/C++使用N=2^32, Java使用N=2^48。此類演算法因為生成的不是真正的隨機數,所以被稱作偽隨機數生成器(Pseudo Random Number Generator)。裝逼需要。不使用蒙特卡洛之類的統計演算法,只把隨機結果顯示出來,人類根本不能分辨真隨機和偽隨機的差別。
我來拋磚引玉吧。
不太認同你所謂高級程序員的說法。應該補充說明是什麼隨機設備發生器(種子)。首先應問的是取隨機數需要什麼分布?(需求)
其次是用什麼隨機設備發生器。(依賴)最後才是演算法吧。(代碼)偽不偽應該取決於演算法和隨機設備,尤其是隨機設備。
系統中斷,外部離散事件服從泊松分布,可是需要的是均勻分布的話,該如何調整?
如果需要正態分布,基於雜訊的隨機設備又如何滿足?至於你說的取內存值,你無法確定在任意一個時間段內是否滿足某種分布,甚至也許根本不滿足均勻分布,即使加演算法也不行。
如果是研究課題,就可以仔細分析。
如果是工程代碼,取決於業務場景的嚴格程度。以上所謂偽隨機,即 num = Random(seed)。也就是說,同樣的seed,其生成的隊列也是一樣。這樣對於加密等涉及安全的演算法極為不利:hacker 可以通過獲取一定長度的隨機數序列來推出seed。
這是偽隨機數的大弊端。這個好像在大陸的高一還是高二課本里都有,明確說了,所謂的隨機數其實是偽隨機數,並不是真正隨機的。
因為偽隨機數在多大的範疇內設計演算法,因為是有演算法產生的,那麼就必然不隨機,隨機這個屬性和演算法本身就是矛盾的,但是你可以通過優化演算法或者設備來使你的隨機數更近隨機。只要是存在某個時刻已知之前的隨機數時能夠預測下一個隨機數的隨機數序列都是偽隨機數序列
使用演算法生成的隨機數都存在循環的問題,所以那麼在收集一段時間後是可以預測下一個隨機數的而在加密學這種情況下,有個重要的前提是加密過程中使用的隨機數是不可預測的
因為在加密中隨機數常用來防止重放攻擊和構造明文攻擊那麼在這樣的情況下使用偽隨機數就會有讓攻擊者在收集足夠的密文信息之後算出密鑰的可能性但是在日常編程使用中(非加密中),只要正確設置隨機數種子,標準的隨機數生成演算法還是很可靠的,至少在少量的獲取隨機數的情況下可以將偽隨機數看作是隨機數來使用我不太懂哈,但我師弟最近在做遺傳演算法,需要隨機數,用的C內置函數實現,這是真的還是假的隨機數呢?還是一個偽的呢?代他問問。懶得去查資料了。
把所有的流程描述出來,並且不使用「隨機」這個詞。那麼你就得到一個為偽隨機函數。
樓上都已經回答了,我來說點題外話。
不要覺得是偽隨機就一無是處,有時候偽隨機就是要比真隨機好用,如:場景重現。例如要記錄一個高級玩家玩的俄羅斯方塊記錄,一般方塊是隨機生成的,所以需要記錄的條件有:1方塊類型 2旋轉角度 3下落位置 而方塊是偽隨機的話,其實只需要記錄隨機種子便可以了。當然2和3也是要記錄的。所以偽隨機數也同樣達到了隨機的效果,這和一些無用的假貨還是有區別
推薦閱讀:
※計算機是怎麼理解隨機的?
※學習編程該如何起步,24歲開始會不會太晚?
※寫代碼工作2年有餘,可總感覺在原地踏步,如何突破?
※參加 Hackathon 發現 SDK 有 Bug 是什麼體驗?
※參加 Go Hack 17 是一種怎樣的體驗?