3

我对 Java RNG 的工作原理非常感兴趣。我读过使用该getLong()方法非常容易,并且有getInt()两个值。我有兴趣在getInt(int n)知道n.

由于getInt(n)通常使用 val = bits % n;并重复它直到bits - val + (n-1) >= 0), 是位next(31)所以 val == bits (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全部1为 s 并且 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 回答