【问题标题】:Random.nextInt returns contiguous same-value integers (frequently)Random.nextInt 返回连续的相同值整数(经常)
【发布时间】:2018-03-12 15:20:50
【问题描述】:

我在运行scala.util.Random().nextInt(3) 81 次时看到如下结果(Java 开发人员,请参阅edit 了解这如何关联):

200010202002112102222211012021020111220022001021101222222022210222220100000100010

注意大的连续块: 000222221112222222222222200000000

直观地说,这个序列看起来并不自然/“现实世界的硬币翻转”是随机的。

例如,要实现6x 连续2s 只有0.4% 机会(AFAIK)和5x 连续值有1.2% 机会......所以我似乎不太可能继续看到输出中的模式是这样的。

这会在现实世界中用 3 面硬币发生吗?或者这是使用 Java 的 Random.nextInt(exclusiveMax) 方法时与“真正随机”的预期偏差?

编辑:

我实际上一直在使用scala.util.Random.nextInt(int),它通过new java.util.Random() 创建一个新的全局java.util.Random

【问题讨论】:

  • 我们无法为您提供我们看不到的代码。没有Random.nextInt(int),所以问题中唯一的代码显然不是您的实际代码(nextInt 是实例方法,而不是类方法)。请添加minimal reproducible example 来演示问题。最有可能的是,您正在使用相同的种子创建 Random 实例。请记住,如果您从相同的种子开始,Random 会产生相同的序列,这就是为什么它是一个 psuedo-随机数生成器。
  • @T.J.Crowder 谢谢,已添加说明。
  • 使用您的示例输出,在第一个之后的 81 个值中,47 个与前一个不同,33 个相同。这对我来说似乎非常错了。 (在一个完美的世界里,你会得到 33%。)样本量很小,这是可信的。如果你在几十万个结果之后得到相同的比例,我会更担心。
  • @JonSkeet 在您建议的测试之后,我看到 33.33% 的样本量更大。

标签: java scala random statistics


【解决方案1】:

这不是玩笑:我会在现实世界中尝试(可能最简单的两枚硬币:正面 = 0,混合 = 1,反面 = 2)。我怀疑你会看到同样的结果。

你只有三个值,所以 2 的机会总是 1:3。你说得很对,得到 2 后,你连续 5 次再得到 2 的几率约为 0.04%,这在 81 次滚动中确实不太可能。但是在获得 2 分之后,您再获得 4 个 的几率(如您所说)是 1.23% - 可能性更大,而且在 81 次投掷中也不足为奇。

在我下面运行程序,我经常在 81 卷批次中运行 3 次,并且经常运行 4 次,但很少运行 5 次,相当很少运行 6 次。所有这些都在很大程度上符合我的预期。

Measuring the randomness of a PRNG 是一个相当复杂的话题。最简单的方法是运行它数百万次,然后看看你是否得到了每个值 ~0.33333333% 的时间。但是,当然,这可能是一百万个 0,然后是一百万个 1,然后是一百万个 2,这将是一个可疑的随机结果。 :-) 但是,如果您想测试您的设置,您可以尝试该 Wikipedia 文章中讨论的几种方法。或订阅真正随机性的来源,如https://www.random.org/。或者一个随机的 USB 设备(尽管我会对其中一个进行大量的尽职调查)。

我的程序:

import java.util.*;

public class E {

    public static void main(String[] args) {
        Random r = new Random();
        Map<Integer,Integer> runs = new TreeMap<>();
        int last = -1;
        int run = 0;
        for (int i = 0; i < 81; ++i) {
            int v = r.nextInt(3);
            if (v != last) {
                if (i != 0) {
                    if (runs.containsKey(run)) {
                        runs.put(run, runs.get(run) + 1);
                    } else {
                        runs.put(run, 1);
                    }
                    System.out.println(" (" + run + ")");
                }
                last = v;
                run = 0;
            }
            ++run;
            System.out.print(v);
        }
        System.out.println("\n****");
        for (Map.Entry e : runs.entrySet()) {
            System.out.println(e.getKey() + ": " + e.getValue());
        }
    }
}

【讨论】:

  • 谢谢!这是我周日下午的排序:)
  • @LawrenceWagerfield:哈哈
猜你喜欢
  • 1970-01-01
  • 2014-07-23
  • 2022-12-12
  • 1970-01-01
  • 2015-02-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-11-09
相关资源
最近更新 更多