随机数生成器重复某些数字太频繁

huangapple go评论62阅读模式
英文:

Random number generator repeates some numbers too often

问题

我正在编写一个彩票抽奖模拟程序作为一个项目。游戏的规则是你需要从49个数字中选择6个数字来赢得游戏。

你赢得游戏的机会是1/13,983,816,因为这是从49个数字中选择6个数字的组合总数。在循环中,每次都会生成六个新的数字。你可以在Go Playground上的演示程序中看到。

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

英文:

I'm writing a lottery draw simulation program as a project. The way the game works is you need to pick the 6 numbers that are draw from the 49 to win.

Your chance of winning is 1/13,983,816 because that's how many combinations of 6 in 49 there are. The <kbd><a href="https://play.golang.org/p/1jdfnW4FOc">demo program on Go playground </a></kbd> generates six new numbers each time around the loop forever.

Each time a new set of numbers is generated I test to see if it already exists and if it does I break out of the loop. With 13,983,816 combinations you would think it would be a long time before the same 6 numbers would repeat but, in testing it fails always before 10000 iteration. Does anyone know why this is happening?

答案1

得分: 7

在我看来,你这里有几个问题。

  1. 你使用的是Go playground,其中的随机性是固定的。这行代码rand.Seed(time.Now().UnixNano())总是产生相同的种子,因为time.Now()是相同的。
  2. 你在模拟中测试了完全不同的事物。我会在最后写一些关于这个的内容。
  3. 如果你想做类似赌博的事情,你必须使用密码学安全的伪随机数生成器,而且Go语言有这个功能。如果你愿意,你可以在这里阅读更多细节(这个答案是针对PHP问题的,但它解释了区别)。

关于概率部分:

你中奖的概率确实是1/C(49, 6) = 1/13,983,816。但这是某人选择一个预定义的号码集的概率。例如,你声称你的中奖号码是{1, 5, 47, 3, 4, 5},现在某人中奖的概率大约是1400万分之一。所以你需要做以下操作:随机选择一组6个号码,然后在循环中将你的新选择与已经找到的号码进行比较。

但你所做的是检查碰撞的概率。也就是说,当有N个人时,其中一些人会选择相同的号码集(甚至不一定是中奖号码集)。这就是所谓的生日悖论。正如你在那里看到的,碰撞的概率随着人数N的增加而急剧增加。

这完全是同样的问题,但你一年的天数是13,983,816,你可以在这里检查,对于这个天数,你只需要5000次迭代就能以0.59%的概率保证会发生碰撞。而通过9000次迭代,你将以0.94的概率找到碰撞。

英文:

In my opinion you have a couple of problems here.

  1. You use Go playground, where your randomness is fixed. This line rand.Seed(time.Now().UnixNano()) always produce the same seed because time.Now() is the same.
  2. You test completely different things with your simulation. I will write about it in the end.
  3. if you want to do something similar to gambling - you have to use cryptographically secure PRNG and Go has it. If you want you can read more details here (the answer is to php question, but it explains the difference).

On the probability part:

The probability of winning your lottery is indeed 1/C(49, 6) = 1/13,983,816. But this is the probability that someone would select an already predefined set of numbers. For example you claim that your winner is {1, 5, 47, 3, 4, 5} and now the probability that someone would win is approximately 1 in 14 mln. So you have to do the following. Randomly select a set of 6 numbers and then compare your new selection in a loop to already found.

But what you do is to check the probability of collision. That having N people some of them would select the same sets (not necessarily even the winning set). This is known as the birthday paradox. And as you see there, the probability of collision increase dramatically with the increase of number of people N.

This is absolutely the same problem, but your number of days in the year is 13,983,816 and you can check here that for this number of days you need only 5000 iterations to guarantee with 0.59 percents that you will get a collision. And with 9000 iterations you will find the collision with probability 0.94.

答案2

得分: 2

我相信你正在解决一个不同的问题,两次抽取结果完全相同的可能性要比出现特定的一次抽取结果要高得多。

这被称为“生日问题”。

英文:

I believe you are solving a different problem, the likelihood that two identical draws show up is much higher than one specific one will show up.

This is known as Birthday Problem

答案3

得分: 0

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

所以,对于原始的生日悖论,有365天,所以根据经验法则,大约19个人就已经有相当大的碰撞机会(真正的答案超过50%的概率是23个人)。

在这里,有13,983,816种可能的结果,经验法则告诉你,通过3739次抽取,你有相当大的碰撞机会(50%的真正答案是4400次抽取)。

英文:

BTW, a rough rule of thumb for the birthday paradox is that if you have N days, you need roundabout sqrt(N) people to get a good chance (around 50%) of a collision.

So, for the original birthday paradox, you have 365 days, so the rule of thumb gives you that with 365^.5 or about 19 people you already have a decent chance of collision (true answer for >50%: 23 people).

Here, with 13,983,816 possible outcomes, the rule of thumb tells you that with 3739 draws you have a pretty good chance of collision (true answer for 50%: 4400 draws).

huangapple
  • 本文由 发表于 2016年2月1日 06:28:43
  • 转载请务必保留本文链接:https://go.coder-hub.com/35120321.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定