【问题标题】:Why does Random.nextLong not generate all possible long values in Java?为什么 Random.nextLong 不能在 Java 中生成所有可能的 long 值?
【发布时间】:2014-03-25 18:10:54
【问题描述】:

Random 类的 nextLong() 方法的 Javadoc 指出

因为类 Random 使用只有 48 位的种子,所以该算法不会返回所有可能的 long 值。 (Random javadoc)

实现是:

return ((long)next(32) << 32) + next(32);

我看到它的方式如下:要创建任何可能的 long,我们应该生成任何可能的 64 位比特模式,具有相同的可能性。假设对 next(int) 的调用给了我们 32 个随机位,那么这些位的连接将是一个 64 个随机位的序列,因此我们生成每个 64 位模式的可能性相等。因此所有可能的长值。

我想编写 javadoc 的人更清楚,我的推理在某种程度上是有缺陷的。谁能解释我的推理在哪里不正确,然后会返回什么样的多头?

【问题讨论】:

  • 我的猜测是这不能生成前半部分等于后半部分的数字。如果他们这样做了,next(32) 将始终生成相同的数字。这意味着每次调用它时总是生成相同的 long。

标签: java random


【解决方案1】:

由于 Random 是伪随机的,我们知道给定相同的种子它将返回相同的值。以他们的话来说,有 48 位种子。这意味着最多可以打印 2^48 个唯一值。如果还有更多,则意味着我们之前在位置

如果我们尝试合并两个结果,我们会看到什么?

|a|b|c|d|e|f|...|(2^48)-1|

以上是一些值。有几对? a-b, b-c, c-d,... (2^48)-1-a。还有 2^48 对。我们不能只用 2^48 对填充 2^64 的所有值。

【讨论】:

    【解决方案2】:

    伪随机数生成器就像巨大的数字环。你从某个地方开始,然后随着你拉出数字,一步一步地绕着圆环移动。这意味着对于给定的种子(初始内部状态),所有后续数字都是预先确定的。因此,由于内部状态只有 48 位宽,所以只有 2 的 48 次方随机数是可能的。因此,由于下一个数字由前一个数字给出,现在很清楚为什么 nextLong 的实现不会生成所有可能的 long 值。

    【讨论】:

    • 这里严格来说不是种子值的长度,而是生成器内部状态的长度。用过的生成器似乎是一样的(虽然我没有查过)。
    • 我不相信这种推理。如果我使用 n
    • 请注意,这种情况下的 step 并不意味着值会上升,直到它们环绕(你可以通过打印一些来判断)。这只是意味着这些值是由初始状态预先确定的。
    • 这里重要的部分(应该用粗体强调)是the next number is given by the previous number
    【解决方案3】:

    假设一个完美的伪随机 K 位生成器是在 2^K 次尝试中创建所有可能的 2^K 种子值的生成器。我们不能做得更好,因为只有 2^K 个状态,每个状态完全由前一个状态决定,并决定下一个状态。

    假设我们将 48 位生成器的输出写成二进制。这样我们得到 2^48 * 48 位。 现在我们可以通过遍历列表并注意接下来的 64 位(在需要时回绕到开头)来准确地说出我们可以获得多少个 64 位序列。这正是我们拥有的位数:13510798882111488。 即使我们假设所有这些 64 位序列都是成对不同的(这一点并不明显),我们还有很长的路要走,直到 2^64: 18446744073709551616。

    我再写一遍数字:

    18446744073709551616 pairwise different 64 bit sequences we need
       13510798882111488 64 bit sequences we can get with a 48 bit seed.
    

    这证明了 javadoc 编写者是对的。随机生成器只能生成所有长值的 1/1844

    【讨论】:

    • 如果生成器有一个 48 位的内部状态,很明显,最多有 2^48 个可能的状态。因此,无论您如何提取 64 位,最多有 2^48 个可能的位序列,而不是完整的 2^64。
    • 在 2^K 次尝试中创建所有可能的 2^K 值的伪随机 K 位生成器是一个非常糟糕的生成器。事实上,我们可以区分它。想想生日悖论。
    • 你说得对,@Henry,现在它也看到了。将相应地编辑我的答案。
    猜你喜欢
    • 1970-01-01
    • 2021-04-30
    • 1970-01-01
    • 1970-01-01
    • 2015-07-16
    • 2019-01-12
    • 1970-01-01
    • 2016-10-16
    • 2012-06-14
    相关资源
    最近更新 更多