簡體   English   中英

當我設置種子時,Java隨機總是返回相同的數字?

[英]Java random always returns the same number when I set the seed?

我需要幫助我正在創建的隨機數生成器。 我的代碼如下(在一個名為numbers的類中):

public int random(int i){
    Random randnum = new Random();
    randnum.setSeed(123456789);
    return randnum.nextInt(i);
}

當我從另一個類調用此方法時(為了生成一個隨機數),它總是返回相同的數字。 例如,如果我這樣做:

System.out.println(numbers.random(10));
System.out.print(numbers.random(10));

它總是打印相同的數字,例如5 5.我需要做什么才能打印兩個不同的數字,例如5 8

我必須設置種子。

謝謝

您需要在整個類中共享Random()實例:

public class Numbers {
    Random randnum;

    public Numbers() {
        randnum = new Random();
        randnum.setSeed(123456789);
    }

    public int random(int i){
        return randnum.nextInt(i);
    }
}

如果您始終設置種子,您將始終得到相同的答案。 這就是種子的設定。

導致您看到的內容有兩個問題。 第一個是代碼為Random實例設置種子值。 第二個是實例方法“random”實例化一個新的Random對象,然后每次立即使用相同的種子設置其種子。 這兩者的組合保證,對於i的相同值,方法“random”將始終返回相同的值,並且它將始終是種子始終生成的序列中的第一個。

假設設置種子是必需的,為了獲得序列中的下一個值而不是每次都獲得序列的相同第一個值,Random的randnum實例每次在其下一個方法被調用之前都不能設置其種子集。 要解決此問題,請將Random的randnum局部變量實例從隨機實例方法的范圍移動到類范圍。 其次,僅在為隨機分配一個Random實例時設置種子,或者僅為了從中獲取相同的結果序列以重新開始。 Random Random的setSeed(long seed)實例方法無法在類范圍內執行,因此構造函數必須使用帶有long種子參數的Random構造函數來設置它。 以下代碼顯示了更改:

public class RandomDemo { // arbitrary example class name
    // lots of class related stuff may be here...

    // still inside the class scope...
    // private is a good idea unless an external method needs to change it
    private Random randnum = new Random(123456789L);
    // the seed guarantees it will always produce the same sequence
    // of pseudo-random values when the next methods get called
    // for unpredicable sequences, use the following constructor instead:
    // private Random randnum = new Random();

    // lots of code may be here...

    // publicly exposed instance method for getting random number
    // from a sequence determined by seed 123456789L
    // in the range from 0 through i-1
    public int randnum(int i) {
        // don't set the seed in here, or randnum will return the exact same integer
        // for the same value of i on every method call
        // nextInt(i) will give the next value from randnum conforming to range i
        return randnum.nextInt(i);
    } // end randnum

    // lots of more code may be here...

} // end class RandDemo

如上所述,上述內容將為您提供確切問題的精確解決方案。 然而,鑒於它的作用,使用強制種子似乎是不尋常的。

如果這是一個類項目或軟件測試,其中序列必須是可預測和可重復的,那么將種子設置為固定值是有意義的。 否則,質疑將種子設置為某個預定值的有效性。 以下解釋更多關於隨機種子,隨機種子以及為何提供種子的規定。

Random有兩個構造函數:

Random()

Random(long seed)

和一個實例方法

setSeed(long seed)

這些都會影響從Random實例獲得的數字序列。 實例方法,

setSeed(long seed)

將Random對象設置為與它剛剛使用與構造函數參數相同的種子實例化時所處的狀態。 僅使用種子值的低48位。

如果在沒有種子的情況下實例化Random對象,則種子將與系統時間相同(以毫秒為單位)。 這確保了,除非兩個Random對象在相同的毫秒內實例化,否則它們將產生不同的偽隨機序列。 僅使用種子值的低48位。 這導致不可預測的偽隨機序列。 每次調用下一個方法時,都不需要浪費計算資源來獲取Random的新實例。

提供Random的種子參數,以便可以實例化一個產生可重復序列的Random對象。 對於給定的種子,無論何時使用該種子,下一種方法中的值序列都保證是相同的序列。 這對於測試將使用偽隨機序列的軟件非常有用,其中結果必須是可預測且可重復的。 在操作中創建不同的不可預測的偽隨機序列是沒有用的。

聲明“我必須設置種子”否定了Random對象的偽隨機序列的任何不可預測性。 這是針對類項目還是軟件測試,其中對於程序的相同輸入,結果必須相同?

在啟動時設置種子一次,而不是每次需要一個新的隨機數。

你使用的不是隨機數發生器,它是一個偽隨機數發生器。 PRNG生成偽隨機數序列,種子選擇序列中的起始點(PRNG可以生成一個或多個序列)。

你是否需要在random(int i)方法中創建new Random() 如果您有責任這樣做,您可以使用,您可以將種子設置為當前時間,雖然這不是故障證明,因為您可以在另一個之后快速調用您的numbers.random(10)最終成為同一個種子。 您可以嘗試使用nanoSeconds(我認為System.nanoTime()?如果setSeed只接受int,我猜它會相乘)。

然而,我建議,如果你被允許這樣做,就是你的方法之外宣布你的隨機。 如果你在你的number類構造函數中實例化你的隨機變量,你可以設置任何種子,只要你調用你的方法,它就會給你一個新的數字。 (如果使用常量種子,每次重新啟動應用程序時它們將是相同的數字組,但是,在這種情況下,您也可以使用時間作為種子)。

最后,如果你同時聲明幾個number類,最后一個問題可能就是。 它們都將具有相同的隨機種子,並為您提供相同的隨機數。 如果發生這種情況,您可以在主類中創建一個static Random數,並在您的數字類中調用它。 這將結合這兩個類,但它會工作。 另一種選擇是向您的number類構造函數發送遞增值,為您實例化的每個number ,並使用您傳遞的值作為種子。

第二種選擇應該對你有好處,如果你被允許這樣做的話。

通常,Random不是真正的隨機而是偽隨機。 這意味着它需要一個給定的種子並使用它來生成一個看似隨機的數字序列(但是可以預測,如果你把相同的種子重復,它會重復)。

如果你沒有放種子,那么第一粒種子將從可變來源(通常是系統時間)中取出。

通常,將使用帶種子的值,以使其重復精確值(例如,用於測試)。 使用Random而不使用種子。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM