web-dev-qa-db-ja.com

Java.util.Randomはどの程度優れていますか?

2つの質問:

入れた種子ごとに異なる数列を取得できますか?

「死んだ」種子はありますか? (ゼロを生成するか、非常に速く繰り返すもの。)

ところで、もしあれば、他にどのPRNGを使用すればよいですか?

解決策:PRNGを使用してゲームを作成するので、暗号的に安全である必要はありません。メルセンヌツイスターを使用します。スピードと巨大な期間。

47
Dove

ある程度、乱数ジェネレータはコースの馬です。 Randomクラスは、合理的に選択されたパラメーターでLCGを実装します。しかし、それでも次の機能を示します。

  • かなり短い期間(2 ^ 48)
  • ビットは等しくランダムではありません( ビット位置のランダム性 に関する私の記事を参照してください)
  • 値の組み合わせのごく一部のみを生成します( " 飛行機に落ちる "の有名な問題)

これらが重要ではない場合、RandomにはJDKの一部として提供される償還機能があります。カジュアルゲームのようなものには十分です(ただし、お金が関わるゲームには適していません)。そのような弱い種子はありません。

XORShiftジェネレーター である別の代替方法は、Javaで次のように実装できます。

public long randomLong() {
  x ^= (x << 21);
  x ^= (x >>> 35);
  x ^= (x << 4);
  return x;
}

非常に安価な操作の場合、これは2 ^ 64-1(ゼロは許可されません)の周期を持ち、値を繰り返し生成するときにインライン化できるほど単純です。さまざまなシフト値が可能です。詳細については、XORShiftジェネレーターに関するGeorge Marsagliaのペーパーを参照してください。生成された数値のビットは同様にランダムであると見なすことができます。主な弱点の1つは、数に多くのビットが設定されていない「ルート」に入ることがあり、このルートから抜け出すには数世代かかることです。

その他の可能性は次のとおりです。

  • さまざまなジェネレーターを組み合わせる(たとえば、XORShiftジェネレーターからの出力をLCGにフィードし、その結果をさまざまなパラメーターを使用してXORShiftジェネレーターの出力に追加する):これにより、さまざまなメソッドの弱点を「スムーズ」にすることができます。結合された発電機の期間が慎重に選択されている場合、より長い期間を与える
  • 「ラグ」を追加します(より長い期間を与えるため):基本的に、ジェネレータは通常、生成された最後の数値を変換し、「履歴バッファ」を格納して、たとえば(n-1023)番目を変換します。

愚かな量のメモリを使用して、本当に必要な期間よりも長い期間を与えるジェネレータは避けてください(宇宙の原子数よりも長い期間があるものは、通常は必要ありません)。また、「長期間」が必ずしも「高品質のジェネレータ」を意味するわけではないことに注意してください(ただし、2 ^ 48はまだ少し低いです!)。

50
Neil Coffey

Zvrbaが言ったように、そのJavaDocは通常の実装を説明しています。 疑似乱数ジェネレータに関するウィキペディアのページ にはかなりの情報があり、 Mersenneツイスター について言及しています。これは暗号的に安全であるとは考えられていませんが、非常に高速でさまざまです Javaでの実装 。 (最後のリンクには2つの実装があります-他にも利用できるものがあると思います。)

暗号化された安全な生成が必要な場合は、ウィキペディアのページをお読みください。さまざまなオプションが利用できます。

10
Jon Skeet

RNGが進むにつれて、Sunの実装は 間違いなく最先端ではない ですが、ほとんどの目的には十分です。暗号化の目的で乱数が必要な場合は Java.security.SecureRandom があり、Java.util.randomよりも高速で優れたものが必要な場合は、Java実装を簡単に見つけることができますネット上のメルセンヌツイスターの。

6

これは ドキュメント で説明されています。線形合同ジェネレーターは理論的にはよく理解されており、それらに関する多くの資料が文献やインターネットで入手できます。同じパラメーターを持つ線形合同ジェネレーターは常に同じ周期的なシーケンスを出力し、シードが決定する唯一のことはシーケンスがどこから始まるかです。したがって、最初の質問に対する答えは「はい、十分な乱数を生成する場合」です。

4
zvrba

私のブログ投稿で答えを見てください:

http://code-o-matic.blogspot.com/2010/12/how-long-is-period-of-random-numbers.html

ランダムには、その状態の最大周期があります(長い、つまり2 ^ 64周期)。これは、2 ^ kに直接一般化できます。必要な数の状態ビットを投資すると、最大周期が得られます。 2Mersenne Twisterには、実際にはshortperiodが比較的あります(上記のブログ投稿のコメントを参照) )。

- おっとっと。ランダムは、longの完全な64ビットを使用する代わりに、48ビットに制限するため、それに応じて、その周期は結局2 ^ 64ではなく2 ^ 48になります。

0