web-dev-qa-db-ja.com

Javaシードを使用した乱数

これは、シードを引数として使用して乱数を生成する私のコードです:

double randomGenerator(long seed) {
    Random generator = new Random(seed);
    double num = generator.nextDouble() * (0.5);

    return num;
}

種を与えて100個の数字を生成しようとするたびに、それらはすべて同じです。
これを修正するにはどうすればよいですか?

44
Rahul Bhatia

同じ種を与えている場合、それは正常です。これはテストを可能にする重要な機能です。

これをチェックして、擬似ランダム生成とシードを理解します。

疑似乱数ジェネレーター

決定論的ランダムビットジェネレーターDRBGとも呼ばれる疑似乱数ジェネレーター(PRNG)は、乱数の特性を近似する一連の数値を生成するアルゴリズムです。シーケンスは、真にランダムなシードを含むPRNGの状態と呼ばれる比較的小さな初期値のセットによって完全に決定されるという点で、真にランダムではありません。

異なるシーケンス(アルゴリズムの調整やデバッグを行わない通常の場合)が必要な場合は、nanoTimeを使用して毎回異なるシードを取得しようとするゼロ引数コンストラクターを呼び出す必要があります。もちろん、このRandomインスタンスはメソッドの外部に保持する必要があります。

コードはおそらく次のようになります。

private Random generator = new Random();
double randomGenerator() {
    return generator.nextDouble()*0.5;
}
72
Denys Séguret

簡単な方法は以下を使用することです:

Random Rand = new Random(System.currentTimeMillis());

これは、Random番号を生成する最良の方法です。

20
Pollar

メソッドスコープで新しいRandomを作成しないでください。クラスメンバーにします。

public class Foo {
   private Random random 

   public Foo() {
       this(System.currentTimeMillis());
   }

   public Foo(long seed) {
       this.random = new Random(seed);
   }

   public synchronized double getNext() {
        return generator.nextDouble();
   }
}

これは一例です。 Randomをこのようにラッピングすると、値が追加されるとは思いません。それを使用しているあなたのクラスに入れてください。

11
duffymo

それがPseudo-RNGの原理です。数字は本当にランダムではありません。それらは決定論的アルゴリズムを使用して生成されますが、シードに応じて、生成される数値のシーケンスは異なります。常に同じシードを使用するため、常に同じシーケンスが取得されます。

6
JB Nizet

問題は、ランダムジェネレータを再度シードすることです。シードするたびに、乱数ジェネレーターの初期状態はリセットされ、生成する最初の乱数は初期状態の後の最初の乱数になります

2
Minion91

1つのシードを使用して複数の数値を生成する場合は、次のようなことができます。

public double[] GenerateNumbers(long seed, int amount) {
    double[] randomList = new double[amount];
    for (int i=0;i<amount;i++) {
        Random generator = new Random(seed);
        randomList[i] = Math.abs((double) (generator.nextLong() % 0.001) * 10000);
        seed--;
    }
    return randomList;
}

同じシードを使用すると、同じリストが表示されます。

2
user5479540

ここのいくつかの例では、新しいRandomインスタンスを作成していますが、これは不要です。また、1つのソリューションのようにsynchronizedを使用する理由もありません。代わりに、 ThreadLocalRandom クラスのメソッドを利用してください。

double randomGenerator() {
    return ThreadLocalRandom.current().nextDouble(0.5);
}
0
Finn