2012-05-21 91 views
2

我有一個程序,它使用了大量的隨機數來決定它需要在做,並且具有基於PRNG的輸出很多很多的執行路徑。在將我的頭髮拉出來試圖調試它之後,我決定讓所有PRNG調用引用相同的Random實例,該實例在實例化時已被播種爲硬編碼數字。這樣,每次運行程序時,都會出現相同的錯誤。 不幸的是,我每次運行它時都會得到不同的錯誤(儘管它看起來行爲幾乎相同)。隨機與某些種子似乎仍然隨機

我搜索的代碼,任何很多很多次錯過的Math.random()的調用和我保證你有沒有。

任何想法?

編輯:我已證實,正在生成的數字是相同的,但行爲仍是不確定的。這個程序不是多線程的。仍然完全困惑。

所以PRNG的表現不如預期,但我仍然有不確定性。非確定性可能會被無意地帶入程序中,有哪些方法?

+2

1.發佈一些代碼。 2.你有使用發生器的多個線程嗎? 3.使用WebStart時,Sun的Random實現中存在一些錯誤,或許是這種情況。 – npe

+0

我無法在少量代碼內重現問題。目前該程序中有幾千行代碼。 –

+0

沒有多個線程,沒有使用WebStart。 –

回答

3

好吧,我想已經找到我的不確定性的來源。我在一個點上迭代HashSet。 HashSet中會被以相同的順序同樣的事情稀少,而是因爲我沒有指定要添加到HashSet的類的散列法,它將被默認爲根據每個實例的存儲位置有些散。

將HashSet的每個實例更改爲LinkedHashSet 似乎現在一直給我一致的結果,現在約30次運行,在此之前它只會給我連續幾次的相同行爲。

1

繼續不確定性的可能原因(按遞減可能性順序):

  • 您還沒有更換所有的PRNG具有相同的隨機實例調用。您可能首先需要檢查:-)一個好的IDE應該可以幫助您追蹤所有對Random類的引用。
  • 引起併發有時間的影響(例如它的事項哪個線程調用PRNG第一)
  • 你有某種形式的外部輸入到系統中(例如,用戶輸入?所採取的行動基於系統計時器?)
  • 您使用的是一些圖書館有這是影響你的程序的德行爲的非確定性元素(例如,一些排序算法使用隨機數這可能會影響結果,他們返回排序)
  • 你在打破某種環境約束條件(例如OutOfMemoryError或IOException錯誤,有時會發生,但以不同方式捕獲和恢復,或者GC決定清除某些軟/弱參考分配辦法)
  • 宇宙射線/硬件錯誤破壞內存
+0

1)我搜索了任何包含'Math'或'random'的文本,還特別引用了Math類,Math.random()方法和Random類,並且項目中沒有任何內容(有一些在包含的外部庫中,但它們不應該影響它,對吧?) 2)根本不做任何多線程,所以不應該發生我相信 3)我正在讀取一些文件,但只有一次在開始 4)不要這麼想,但我會考慮這個 5)我只是移動到更高的高度:) –

+0

關於你的第四點,如果我沒有捕捉到任何問題,這應該不是問題任何地方都有例外,應該如何? –

+0

@LyndenShields - 不,這是不正確的。如果未經檢查的異常未被子線程捕獲,則線程可導致「異常恢復」。子線程死了,但這可能會被忽視/不註釋,程序的其餘部分仍在繼續。 –

2

好了,這似乎是一個巫術。嘗試創建一個自定義PRNG,它包裝一個Random對象並使用堆棧跟蹤記錄調用。

public class CustomRNG { 

    private static Logger logger = Logger.getLogger(CustomRNG.class.getName()); 
    private static Random random = new Random(1234); 

    public int nextInt() { 

     int val = random.nextInt(); 
     log(val); 

     return val; 
    } 

    private void log(int value) { 
     logger.log(Level.INFO, "value: " + value, new Throwable()); 
    } 
} 

這將記錄每個呼叫nextInt,包括值和一個堆棧跟蹤(如果你喜歡增加呼叫計數)。 嘗試運行你的應用程序幾次,看看在哪一點(堆棧跟蹤)這種分歧。

+0

btw; Logger.getlogger而不是getInstance,並且在日誌方法中有一個超值的結束符。 –

+0

也添加了nextDouble()方法,因爲這就是我正在使用的方法和一個新的日誌(雙值)匹配。 執行該程序幾次,直到它分開,並且分析結果。花了一段時間,但最終我可以看到,該程序的執行路徑已經分散,而不會產生分歧的數字。 我不知道是否有某種方法可以在運行之間更改stderr的順序?在Java中,只要調用System.err.println,緩衝區就會刷新,對吧? –

+0

Java標準庫中是否存在非確定性的方法?例如(我知道這不是真的,只是爲了解釋我的觀點),也許像Math.round()這樣的東西會隨機選擇哪個int返回,如果它正好在中間。 –