我不得不從一個數組返回一個隨機元素,所以我想出了這個佔位符:直接使用系統的時間來獲得隨機數
return codes[(int) (System.currentTimeMillis() % codes.length - 1)];
現在比我想起來了,我很想用它在真實的代碼。無論如何,播種機使用系統時間作爲種子,所以爲什麼不直接使用這個時間?作爲獎勵,我免於擔心許多RNG的非隨機低位。這黑客回來咬我? (語言是Java的,如果這是相關的。)
我不得不從一個數組返回一個隨機元素,所以我想出了這個佔位符:直接使用系統的時間來獲得隨機數
return codes[(int) (System.currentTimeMillis() % codes.length - 1)];
現在比我想起來了,我很想用它在真實的代碼。無論如何,播種機使用系統時間作爲種子,所以爲什麼不直接使用這個時間?作爲獎勵,我免於擔心許多RNG的非隨機低位。這黑客回來咬我? (語言是Java的,如果這是相關的。)
使用內置了java.util.Random。 有效的Java(第二版,第215頁)的項目47把它提出來作爲爲什麼你應該更喜歡使用您自己的標準庫的例子。它首先解釋Math.abs(rnd.nextInt() % n
是一種不好的方法,因爲它不會產生真正的隨機分佈,您應該簡單地使用rnd.nextInt(n)
來代替。它接着說:
要編寫一個版本的
random
方法可以解決這三個 惹麻煩的,你必須知道一個公平 量大約僞隨機數 發電機,數論,以及兩個的 補算術。...
你不必與
nextInt(int)
是如何做的工作細節關心自己。具有算法背景的高級工程師花費了大量的時間來設計,實施和測試該方法,然後將其展示給該領域的多位專家,以確保它是正確的。然後,圖書館進行了測試,發佈,並在數十年的大部分時間裏被數百萬程序員廣泛使用。該方法中尚未發現任何缺陷,但是如果發現缺陷,將在下一步中修復。通過使用標準庫,您可以充分利用編寫它的專家的知識以及在您之前使用它的人的經驗。
應當注意的是,即使例如不完全使用相同的代碼,你是在暗示一個,它更真實的你的榜樣。取一個隨機整數的其餘部分偏離分佈,但至少它有一些隨機性的出現。只是調整時間是一種更糟的做法。
你低估了僞隨機數發生器的複雜性。你所建議的方法存在的問題是,這種分佈不僅可能不是隨機的,而且它也是真正可預測的。有真實世界的黑客利用可預測種子的僞隨機數發生器在撲克中作弊。 構建安全軟件(Viega和McGraw,2002)包含討論這些問題的完整章節。
下面是一個很好的例子,說明如何在實踐中破壞可憐的PRNGs。 1999年,Cigital的軟件安全組發現了德克薩斯Hold'em Poker的一個嚴重缺陷,該軟件由ASF Software,Inc.分發。該漏洞使得作弊的玩家可以計算出每隻手在實際使用時的確切甲板時間。這意味着使用該漏洞的玩家可以知道每個對手手中的牌以及組成翻牌的牌(在下注一輪後,牌面朝上)。騙子可以「知道什麼時候握住他們,知道何時每次摺疊他們」。一個惡意攻擊者可以利用這個漏洞在沒有被捕獲的情況下欺騙無辜的玩家。 (頁238)
下面是討論隨機性的複雜性兩個問題:
這是一份文件,只有幾周大(但一個真正蹩腳的標題),描述瞭如何利用PRNG的可預測種子來攻擊PHP的會話生成算法:
唯一的原因,我能想到的反對是這樣的:如果系統時鐘總是返回16的倍數(這可以在Windows發生的XP機器,例如)什麼,和你的陣列恰好是16的長度?
通常有很好的理由,標準庫類已經在第一時間得到了發展。
雖然它可能是涼着編寫自己的代碼,以解決學術環境問題,在商務場合進行實驗,最好使用久經考驗庫和不太可能在應用程序中創建不必要的行爲的技術。
如果您在使用你的技術設置,我會強烈建議你寫詳盡測試用例來測試邊界條件和大量的數據點。這將幫助您在代碼投入生產之前調試代碼。
這是一個可怕的想法!別想它!連續調用這個自制的「僞隨機數生成器」將被強烈關聯,以至於你可能只需要使用一個簡單的計數器。 (其中,如果你錯過了,我不推薦)
編輯補充:順便說一句,正如你編碼它,你的數組索引偶爾會是-1。這也是一個可怕的想法。