【问题标题】:Get seed of Java's RNG with getInt(int n) method使用 getInt(int n) 方法获取 Java 的 RNG 种子
【发布时间】:2013-12-09 09:03:22
【问题描述】:

我对 Java RNG 的工作原理非常感兴趣。我读过使用getLong() 方法和getInt() 和两个值非常容易。我有兴趣通过知道n 的价值获得getInt(int n) 的种子。

由于getInt(n) 通常使用 val = bits % n; 并重复它直到 bits - val + (n-1) >= 0),是位 next(31) 所以 val == bits (mod n)

我已经测试了一个蛮力测试所有可能的与初始数字一致的数字对,但这对于计算机来说非常长且困难。

关于如何有效获取种子的任何其他想法?

【问题讨论】:

  • 你在哪里读到getLong 很容易?另外,您是指第一次调用getInt 还是任意调用?
  • stackoverflow.com/questions/15236151/… 并在不带参数的情况下调用 getInt() 2 次​​span>

标签: java random random-seed


【解决方案1】:

您应该能够为此使用反射:

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
}

但是,maskmultiplier 只是定义为:

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

由于mask 是最低有效 48 位的所有 1s 并且 XOR 是可逆的,因此当(且仅当!)它小于 (1L

输出:

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

另见this answer on StackOverflow

【讨论】:

  • 有了结果种子并进行了操作,是不是不能扣除原始种子?
  • 让我检查一下,我认为如果初始种子小于 2^48 是可能的
  • 查看我的更新答案,了解如何取回初始种子值。
  • 添加了角落案例(1L &lt;&lt; 48)-1(1L &lt;&lt; 48)的输出。
  • 谢谢,这正是我要找的:D
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-01-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-10-25
  • 1970-01-01
  • 2013-02-10
相关资源
最近更新 更多