10

upperBoundつまり、いくつかの特定のパラメーターを使用して、連続して 16 個を超える偶数を生成することはありません。

Random random = new Random();

int c = 0;
int max = 17;
int upperBound = 18;

while (c <= max) {
    int nextInt = random.nextInt(upperBound);
    boolean even = nextInt % 2 == 0;
    if (even) {
        c++;
    } else {
        c = 0;
    }
}

この例では、コードは永遠にループしますupperBoundが、たとえば 16 になるとすぐに終了します。

この動作の理由は何ですか? メソッドの javadoc に注意事項がいくつかありますが、理解できませんでした。


UPD1 : コードは奇数の上限で終了しているように見えますが、偶数の上限でスタックする可能性があります


UPD2c :コメントで提案されているように、統計を取得するようにコードを変更しました。

Random random = new Random();

int c = 0;
long trials = 1 << 58;
int max = 20;
int[] stat = new int[max + 1];

while (trials > 0) {
    while (c <= max && trials > 0) {
        int nextInt = random.nextInt(18);
        boolean even = nextInt % 2 == 0;
        if (even) {
            c++;
        } else {
            stat[c] = stat[c] + 1;
            c = 0;
        }
        trials--;
    }
}

System.out.println(Arrays.toString(stat));

現在20、行の偶数に到達しようとしています - より良い統計を取得するためにupperBound18.

結果は驚くべきものでした。

[16776448, 8386560, 4195328, 2104576, 1044736, 
 518144, 264704, 132096, 68864, 29952, 15104, 
 12032, 1792, 3072, 256, 512, 0, 256, 0, 0]

最初は予想どおり 2 分の 1 に減少しますが、最後の行に注意してください。ここでは気が狂い、キャプチャされた統計は完全に奇妙に見えます。

対数スケールの棒グラフは次のとおりです。

c統計

c256 回の値を取得する方法は、17さらに別の謎です

4

3 に答える 3

2

Random の実装では、単純な線形合同式を使用します。このような数式には、自然な周期性と、それらが生成するシーケンス内のあらゆる種類の非ランダム パターンがあります。

あなたが見ているのは、これらのパターンの 1 つのアーティファクトです...意図的なものではありません。偏見の例ではありません。むしろ、それは自己相関の一例です。

より良い (より多くの「乱数」) 数値が必要な場合は、SecureRandomではなくを使用する必要がありますRandom

そして、「なぜそのように実装されたのか」に対する答えは...パフォーマンスです。への呼び出しはRandom.nextInt、数十または数百のクロック サイクルで完了できます。への呼び出しSecureRandomは、少なくとも 2 桁、場合によってはそれ以上遅くなる可能性があります。

于 2013-07-24T10:20:28.077 に答える
1

移植性のために、Java は、実装が java.util.Random に対して下位の LCG メソッドを使用する必要があることを指定しています。この方法は、複雑なシミュレーションやモンテカルロ法など、乱数を真剣に使用する場合にはまったく受け入れられません。Marsaglia の MWC や KISS など、より優れた PRNG アルゴリズムを備えたアドオン ライブラリを使用します。Mersenne Twister および Lagged Fibonacci Generators も、多くの場合問題ありません。

これらのアルゴリズム用の Java ライブラリがあると確信しています。それがあなたのために働くなら、私はJavaバインディングを備えたCライブラリを持っています: ojrandlib

于 2013-07-24T10:23:49.580 に答える