【问题标题】:How to get a 50/50 chance in random generator如何在随机生成器中获得 50/50 的机会
【发布时间】:2013-03-08 02:23:48
【问题描述】:

我试图在随机生成器中获得 1 或 2 的 50/50 机会。

例如:

Random random = new Random();
int num = random.nextInt(2)+1;

此代码将输出 1 或 2。

假设我循环运行它:

for ( int i = 0; i < 100; i++ ) {
    int num = random.nextInt(2)+1 ;
}

在这种情况下,如何使生成器为 1 和 2 生成相等的数字?

所以我希望这个循环生成 50 次数字 1 和 50 次数字 2。

【问题讨论】:

  • 正如许多其他人所指出的,我认为您在这里感到困惑:如果您掷硬币 100 次,您的 预期 是 50 次正面。 0 到 100 之间的任何数字都是可能的,但概率不同。我认为你爱上了en.wikipedia.org/wiki/Gambler's_fallacy
  • 其实你的期望不应该是 50 头,而是 45 到 55 头之间... :D。只是最有可能出现 50 个正面(发生这种情况的可能性约为 8%)
  • @AntonRoth, no.

标签: java


【解决方案1】:

编辑: 我了解,如果您希望准确地完成 50-50 个结果,那么我的回答不准确。您应该使用预先填充的集合,因为使用任何类型的随机性都无法实现。考虑到这一点,我的回答对于问题的标题仍然有效,所以,就是这样:

好吧,您不需要 rnd 生成器来执行此操作。 来自 javascript,我会选择一个班轮:

return Math.random() > 0.5 ? 1: 2;

解释:Math.random() 返回一个介于 0(含)和 1(不含)之间的数字,因此,我们只检查天气是否大于 0.5(中间值)。理论上有 50% 的变化。

对于更通用的用途,您只需将 1:2 替换为 true:false

【讨论】:

    【解决方案2】:

    一种方法:用 50 个 1 和 50 个 2 填写 ArrayList&lt;Integer&gt;,然后调用 Collection.shuffle(...)

    【讨论】:

    • 假设@Sulaiman 实际上想要 50 个 1 和 2,就是这样。但必须指出,实际的随机性已经消失(这可能导致 47 个 1 和 53 个 2 或类似情况)。
    • @Mercurybullet:我同意 100%。像往常一样,确切的解决方案完全取决于他的要求
    • 生成随机序列为什么这么难?
    【解决方案3】:

    50/50 使用 Random.nextBoolean()

    非常简单
    private final Random random = new Random();
    
    private int next() {
      if (random.nextBoolean()) {
        return 1;
      } else {
        return 2;
      }
    }
    

    测试运行:

    final ListMultimap<Integer, Integer> histogram = LinkedListMultimap.create(2);
    for (int i = 0; i < 10000; i++) {
        nal Integer result = Integer.valueOf(next());
      histogram.put(result, result);
    }
    for (final Integer key : histogram.keySet()) {
      System.out.println(key + ": " + histogram.get(key).size());
    }
    

    结果:

    1: 5056
    2: 4944
    

    【讨论】:

    • 他想要(据我了解)50 1s 和 50 2s 完全。您发布的内容将与他已有的结果相同。
    • 如果首选三元运算符private int next() { return random.nextBoolean() ? 1 : 2; }
    【解决方案4】:

    random 无法实现这一点。如果您正好需要 50 个 1 和 50 个 2,您应该尝试这样的操作:

    int[] array = new int[100];
    for (int i = 0; i < 50; ++i)
     array[i] = 1;
    for (int i = 50; i < 100; ++i)
     array[i] = 2;
    
    shuffle(array); // implement shuffling algorithm or use an already existing one
    

    【讨论】:

      【解决方案5】:

      您可以在此过程中调整概率,以便获得一个的概率随着您获得的更多而降低。这样一来,您并不总是有 50% 的机会获得一个,但您可以获得预期的结果(正好 50 个):

      int onesLeft = 50;
      
      for(int i=0;i<100;i++) {
        int totalLeft = 100 - i;
        // we need a probability of onesLeft out of (totalLeft)
        int r = random.nextInt(totalLeft);
        int num;
        if(r < onesLeft) {
          num = 1;
          onesLeft --;
        } else {
          num = 2;
        }
      }
      

      这比洗牌有一个优势,因为它以增量方式生成数字,因此不需要内存来存储数字。

      【讨论】:

      • 但是分布不会是均匀的,你很可能会用相同的数字填充。
      • @lechlukasz,我想过这一点,但我似乎无法证明或反驳这一点。可以吗?
      • @lechlukasz,实验反驳了你的说法。
      • 我还有一个证明草图:假设该算法对大小为 (n-1) 的数组进行了统一的洗牌,我们可以通过观察选择的第一个数字的概率分布将其扩展到大小为 n是正确的,算法的其余部分是大小为 (n-1) 的洗牌。改组空列表的基本情况是微不足道的。
      • 也许将证明框定为:我需要进行多少次试验才能获得第一个数字的 50 个或第二个数字的 50 个?我们会发现最多这将需要 99 次试验(在这种情况下,您达到 49/49,然后打破平局)。因此,为了获得相等的 50/50,我们将填充其他数字之一以匹配。在其他所有情况下,在第 99 次试验之前,一方将达到 50,这将导致另一个数字的更多填充达到 100 次试验。
      【解决方案6】:

      您已经成功创建了一个随机生成器,它以相同的概率返回12

      正如(许多)其他人所提到的,您的下一个请求,即在 100 次试验中强制 精确 50/50 分布,不符合随机数生成。如https://math.stackexchange.com/questions/12348/probability-of-getting-50-heads-from-tossing-a-coin-100-times 所示,这种情况发生的现实预期仅为 8% 左右。因此,即使您可能预计每个都有 50 个,但 准确 结果实际上是相当罕见的。

      大数定律指出,随着试验次数的增加,您应该接近预期值。

      那么对于您的实际问题:在这种情况下,如何使生成器为 1 和 2 生成相等的数字?

      我能想到的最好(幽默)答案是:“无限循环运行。”

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2012-02-21
        • 1970-01-01
        • 1970-01-01
        • 2012-05-28
        • 1970-01-01
        • 2018-04-03
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多