【问题标题】:Why does this not seem to be random?为什么这似乎不是随机的?
【发布时间】:2014-02-02 00:16:18
【问题描述】:

我正在运行一个程序,就像其中一个游戏一样,人们试图猜测 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%。 但数据并没有反映出这一点。

【问题讨论】:

  • 我假设您希望它接近 50?
  • 另外,你为什么要set(l)同一个数可能让不同的人猜到。
  • 不,这是你推理的缺陷。您期望结果是什么,为什么?
  • 考虑一个更简单的案例。假设只有两个人,每个人都可以猜测 0 或 1,所以猜测列表将是 [0,0]、[0,1]、[1,0] 或 [1,1]。不同猜测的预期数量是多少?
  • 您需要阅读Birthday Paradox

标签: python math random statistics average


【解决方案1】:

如果这是一个完全平坦的分布,您会期望平均值为 100,这意味着每个人的猜测都不同。但是,您知道这种情况的随机性远低于您有重复的情况。您在随机序列中得到重复数字这一事实应该是令人欣慰的。

您在这里所做的只是在非常小的集合中测量某种唯一性:涉及 100 个随机值的实验的 1000 次重复。如果您使用某种自举算法进行采样,您可能会更好地理解这一点。

此外,如果您将重复次数扩大到数百万,并可能测量样本分布(而不仅仅是平均值),您将对所获得的结果更有信心。

可能是伪随机生成器具有在与范围相同长度的序列内产生大约 60-70% 的非重复值的特性。但是,您需要尝试更多的样本以及不同的随机种子。否则你的结果毫无意义。

【讨论】:

    【解决方案2】:

    您的代码用于查找 100 个人每人猜测 1 到 100 的平均 唯一猜测次数。 至于为什么它会收敛到 63 左右的数字...您应该将您的问题发布到数学 Stack Exchange。

    【讨论】:

      【解决方案3】:

      我修改了您的代码,使其将已生成的序列作为输入,而不是计算随机数:

      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
      

      如您所见,结果与我们之前看到的以及您自己的观察结果一致。我相信一点组合数学就可以解释这一切。

      【讨论】:

        猜你喜欢
        • 2014-01-08
        • 1970-01-01
        • 1970-01-01
        • 2012-04-18
        • 2022-10-14
        • 1970-01-01
        • 2011-05-21
        • 1970-01-01
        • 2020-11-26
        相关资源
        最近更新 更多