我正在运行一个程序就像其中一个游戏人们试图猜测0到100之间的数字,其中有100个人猜测。我然后平均了多少不同的猜测。
import random
def averager(times):
tests=[]
for i in range(times):
l=[]
for i in range(0,100):
l.append(random.randint(0,100))
tests.append(len(set(l)))
return (sum(tests))/len(tests)
print(averager(1000))
由于某种原因,不同猜测的数量平均为63.6
为什么会这样?是否是由于python随机库中存在缺陷?
在人们猜测1到10之间的数字
的情况下第一个人有100%的几率猜测以前未被提及的数字
第二个人有90%的机会猜测以前未被提及的数字
第三人有80%的机会猜测以前未被提及的数字
依旧......
猜测新号码的平均机会(按我的推理)为55%。 但数据并未反映这一点。
答案 0 :(得分:2)
您的代码用于查找由100个人猜测1到100之间数字的平均唯一猜测次数。 至于它为什么会收敛到大约63的数字......你应该把你的问题发布到数学堆栈交换。
答案 1 :(得分:0)
如果这是一个完全平坦的分布,你会发现平均值是100,这意味着每个人的猜测都不同。但是,您知道这种情况比您有重复的情况更不随机。你在随机序列中得到重复数字这一事实应该令人感到安慰。
你在这里所做的只是测量非常小的集合中的某种独特性:即 1000次重复涉及100个随机值的实验。如果您使用某种自举算法从中进行采样,您可能会对此有更好的认识。
此外,如果您将重复次数扩大到数百万,并且可能测量样本分布(而不仅仅是平均值),您将对您获得的结果更有信心。
伪随机生成器可能具有在与该范围相同的序列内产生大约60-70%的非重复值的特性。但是,您需要尝试更多的样本以及不同的随机种子。否则你的结果毫无意义。
答案 2 :(得分:0)
我修改了你的代码,因此它将已经生成的序列作为输入,而不是计算随机数:
def averager(seqs):
tests = []
for s in seqs:
tests.append(len(set(s)))
return float(sum(tests))/len(tests)
然后我创建了一个函数,为任何给定数量的人返回所有可能的选项并猜测范围:
def combos(n, limit):
return itertools.product(*((range(limit),) * n))
(我喜欢关于Python的一个原因是,将一个函数分解为琐碎的部分很容易。)
然后我开始测试越来越多的数字:
for n in range(2,100):
x = averager(combos(n, n))
print n, x, x/n
2 1.5 0.75
3 2.11111111111 0.703703703704
4 2.734375 0.68359375
5 3.3616 0.67232
6 3.99061213992 0.66510202332
7 4.62058326038 0.660083322911
8 5.25112867355 0.656391084194
这个算法有一个可怕的复杂性,所以此时我得到了一个MemoryError。正如您所看到的,随着人数和猜测范围的不断增加,独特结果的百分比不断下降。
用随机数重复测试:
def rands(repeats, n, limit):
for i in range(repeats):
yield [random.randint(0, limit) for j in range(n)]
for n in range(10, 101, 10):
x = averager(rands(10000, n, n))
print n, x, x/n
10 6.7752 0.67752
20 13.0751 0.653755
30 19.4131 0.647103333333
40 25.7309 0.6432725
50 32.0471 0.640942
60 38.3333 0.638888333333
70 44.6882 0.638402857143
80 50.948 0.63685
90 57.3525 0.63725
100 63.6322 0.636322
正如您所看到的,结果与我们之前看到的以及您自己的观察结果一致。我相信一些组合数学可以解释这一切。