随机数生成器过于频繁地重复某些数字

Random number generator repeates some numbers too often

我正在编写一个彩票模拟程序作为一个项目。游戏的运作方式是您需要从 49 中选出 6 个号码才能获胜。

您获胜的机会是 1/13,983,816,因为这就是 49 中 6 的组合数。 demo program on Go playground 每次循环都会生成六个新数字。

每次生成一组新数字时,我都会测试它是否已经存在,如果存在,我就会跳出循环。对于 13,983,816 种组合,您可能会认为需要很长时间才能重复相同的 6 个数字,但在测试中它总是在 10000 次迭代之前失败。有谁知道为什么会这样?

我相信您正在解决一个不同的问题,两个相同的抽奖出现的可能性比一个特定的抽奖出现的可能性要高得多。

这被称为Birthday Problem

我认为你这里有几个问题。

  1. 你使用 Go playground,你的随机性是固定的。此行 rand.Seed(time.Now().UnixNano()) 总是产生相同的种子,因为 time.Now() 是相同的。
  2. 你用你的模拟测试完全不同的东西。我会写在最后。
  3. 如果你想做类似于赌博的事情 - 你必须使用 cryptographically secure PRNG and Go has it. If you want you can read more details here(答案是 php 问题,但它解释了区别)。

概率部分:

中奖的概率确实是1/C(49, 6) = 1/13,983,816。但这是有人 select 一组已经预定义的数字的概率。例如,您声称您的获胜者是 {1, 5, 47, 3, 4, 5},现在某人获胜的概率约为 1400 万分之一。因此,您必须执行以下操作。随机 select 一组 6 个数字,然后将循环中的新 selection 与已找到的进行比较。

但是你做的是检查碰撞的概率。有 N 个人,其中一些人会 select 相同的组(甚至不一定是获胜组)。这被称为 birthday paradox。并且如你所见,碰撞的概率随着人数N的增加而急剧增加。

这完全是同一个问题,但是你一年中的天数是 13,983,816 你可以 check here 对于这个天数你只需要 5000 次迭代来保证 0.59%你会发生碰撞。通过 9000 次迭代,您会发现碰撞概率为 0.94。

顺便说一句,生日悖论的一个粗略经验法则是,如果你有 N 天,你需要迂回 sqrt(N) 人才能有很好的机会(大约 50%)发生碰撞。

所以,对于最初的生日悖论,你有 365 天,所以经验法则给你 365​​^.5 或大约 19 个人你已经有相当大的碰撞机会(>50% 的正确答案:23 人)。

在这里,有 13,983,816 种可能的结果,经验法则告诉您,如果有 3739 次平局,您就有很大的机会发生碰撞(50% 的正确答案:4400 次平局)。