ウィキペディアから(@ helloworld922 が投稿した引用によって言及された引用):
LCG のさらなる問題は、m が 2 の累乗に設定されている場合、生成されたシーケンスの下位ビットの周期がシーケンス全体よりもはるかに短いことです。一般に、基数 b 表現の n 番目の最下位桁は、ある整数 k に対して bk = m である場合、出力シーケンスの最大周期 bn で繰り返されます。
さらに、それは続きます (私のイタリック体):
m が 2 のべき乗である場合の LCG の下位ビットは、いかなる程度のランダム性についても信頼すべきではありません。実際、モジュラス項に 2n を代入するだけで、下位ビットが非常に短いサイクルを通過することがわかります。特に、m が 2 のべき乗である場合のフルサイクル LCG は、奇数と偶数の結果を交互に生成します。
結局のところ、その理由はおそらく歴史的なものです。Sun の人々は何かが確実に機能することを望んでおり、Knuth 式は 32 ビットの有効ビットを与えました。java.util.Random
API には次 のように記載されていることに注意してください(私のイタリック体):
Random の 2 つのインスタンスが同じシードで作成され、それぞれに対して同じ一連のメソッド呼び出しが行われた場合、それらは同一の数列を生成して返します。このプロパティを保証するために、特定のアルゴリズムがクラス Random に指定されています。Java 実装は、Java コードの完全な移植性のために、クラス Random に対してここに示されているすべてのアルゴリズムを使用する必要があります。ただし、クラス Random のサブクラスは、すべてのメソッドの一般規約に準拠している限り、他のアルゴリズムを使用することが許可されています。
そのため、参照実装としてこれにこだわっています。ただし、別のジェネレーターを使用できない (および Random をサブクラス化するか、新しいクラスを作成する) ことができないという意味ではありません。
同じウィキペディアのページから:
MMIX by ドナルド・クヌース m=2 64 a=6364136223846793005 c=1442695040888963407
あなたのための64ビット式があります。
(Knuth が指摘しているように) 乱数は注意が必要であり、必要に応じてjava.util.Random
、64 ビットの数値が必要な場合は、2 回呼び出してビットを連結するだけで問題ない場合があります。本当に統計的性質を気にするならMersenne Twisterのようなものを使うか、情報漏洩・予測不可能性を気にするなら使ってみてくださいjava.security.SecureRandom
。