3

私は Java RNG がどのように機能するかにかなり興味があります。getLong()メソッドを使用すると非常に簡単で、getInt()と 2 つの値があることを読みました。getInt(int n)の値を知ってシードを取得することに興味がありnます。

getInt(n)通常使用し val = bits % n;、 まで繰り返すので、bits - val + (n-1) >= 0)ビットnext(31)なので val == ビット (mod n)

最初の数字と一致する可能性のあるすべての数字のペアをテストするブルートフォースをテストしましたが、これは非常に長く、コンピューターにとっては困難です。

効率的な方法でシードを取得する方法について、他に何かアイデアはありますか?

4

1 に答える 1

2

これにはリフレクションを使用できるはずです。

Random r = new Random(1);

Field f;
try {
    f = r.getClass().getDeclaredField("seed");
    f.setAccessible(true);
    AtomicLong seed = (AtomicLong) f.get(r);
    System.out.println("seed: " + seed);

    f = r.getClass().getDeclaredField("mask");
    f.setAccessible(true);
    Long mask = (Long) f.get(r);
    System.out.println("mask: " + mask);

    f = r.getClass().getDeclaredField("multiplier");
    f.setAccessible(true);
    Long multiplier = (Long) f.get(r);
    System.out.println("multiplier: " + multiplier);


    long initialSeed = (seed.longValue() ^ multiplier);
    System.out.println("restored initial seed: " + initialSeed);
} catch (NoSuchFieldException e1) {
} catch (SecurityException e2) {
} catch (IllegalAccessException e3) {
} catch (IllegalArgumentException e4) {
}   

私のマシンでの出力:

seed: 25214903916
mask: 281474976710655
multiplier: 25214903917
restored initial seed: 1

が設定されている場合seed、値はスクランブルされます。

public Random(long seed) {
    if (getClass() == Random.class)
        this.seed = new AtomicLong(initialScramble(seed));
    else {
        // subclass might have overriden setSeed
        this.seed = new AtomicLong();
        setSeed(seed);
    }
}

private static long initialScramble(long seed) {
    return (seed ^ multiplier) & mask; // (seed XOR multiplier) AND mask
}

ただし、maskandmultiplierは次のように定義されています。

private static final long mask = (1L << 48) - 1;
private static final long multiplier = 0x5DEECE66DL;

最下位 48 ビットはmaskすべて1s であり、XOR は可逆的であるため、初期シードが (1L << 48) より小さい場合、つまり 2^48 の場合にのみ元のシードを取得できます。

次の出力:

Random r = new Random((1L << 48)-1);

seed: 281449761806738
mask: 281474976710655
multiplier: 25214903917
restored initial seed: 281474976710655

とのために:

Random r = new Random((1L << 48));

seed: 25214903917
mask: 281474976710655
multiplier: 25214903917
restored initial seed: 0

StackOverflow のこの回答も参照してください

于 2013-11-24T19:08:15.220 に答える