【问题标题】:How to obtain all possible values returnable by Random.nextLong?如何获取 Random.nextLong 可返回的所有可能值?
【发布时间】:2021-04-30 19:10:35
【问题描述】:

Random#nextLong() 文档指出此方法不会返回所有可能的 long 值:

从这个随机数生成器的序列中返回下一个伪随机、均匀分布的 long 值。 nextLong的通用合约是伪随机生成并返回一个long值。方法 nextLong 由 Random 类实现,好像是:

public long nextLong() {
    return ((long) next(32) << 32) + next(32);
}

由于类 Random 使用只有 48 位的种子,此算法不会返回所有可能的长值

例如,数字 8090327796378429294 是可生成的,但数字 8090327796378429295 不是,尽管它们的唯一区别是一个最低有效位,并且值本身是 63 位长。

有一种方法可以使用以下算法了解nextLong() 是否可以返回值:

public class JavaRandom {
    private static final long ADD = 0xBL;
    private static final long MULT = 0x5DEECE66DL;
    private static final long TWO16 = 1L << 16;
    private static final long MASK_31 = (1L << 31) - 1;
    private static final long MASK_32 = (1L << 32) - 1;
    private static final long MASK_48 = (1L << 48) - 1;

    public static boolean canBeGeneratedByJavaRandom(long randomValue) {
        long i1 = (randomValue >> 32) & MASK_32;
        long i2 = (randomValue & MASK_32);
        if (i2 > MASK_31) {
            i1 = i1 + 1;
        }

        long front = i1 << 16;
        for (long i = 0; i < TWO16; i++) {
            long seed = front | i;
            long i22 = (((seed * MULT) + ADD) & MASK_48) >> 16;
            if (i22 == i2) {
                return true;
            }
        }

        return false;
    }
}

如何在不对每个可能的 64 位数字运行此检查的情况下获取 nextLong() 可以生成的所有值?在收集所有值之前调用nextLong() 感觉不合理,而且可能存在冲突。

【问题讨论】:

    标签: java random random-seed


    【解决方案1】:

    鉴于 setSeed 函数完全使用传入值的低 48 位来设置种子,您可以简单地遍历从 0(1L &lt;&lt; 48) - 1setSeed 的所有 seed 值到每个其中,然后为每个种子调用一次nextLong()

    更多信息:

    • This answer 指出可以从 2 个连续的 nextInt() 值中确定种子,因此没有两个不同的种子会生成相同的 2 个连续的 nextInt() 值。
    • 文档指出nextInt() 调用next(32),而nextLong() 获得2 个连续next(32) 值的值。

    从以上两点来看,不同的种子值会产生不同的nextLong()值。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-01-18
      • 2012-07-12
      • 2018-07-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-10-29
      相关资源
      最近更新 更多