我写了一个程序,记录了2个公平骰子需要掷多少次,以匹配我们期望的每个结果的概率。在
我认为这是可行的,但我想知道是否有一种更适合资源的方式来解决这个问题。在
import random
expected = [0.0, 0.0, 0.028, 0.056, 0.083,
0.111, 0.139, 0.167, 0.139, 0.111,
0.083, 0.056, 0.028]
results = [0.0] * 13 # store our empirical results here
emp_percent = [0.0] * 13 # results / by count
count = 0.0 # how many times have we rolled the dice?
while True:
r = random.randrange(1,7) + random.randrange(1,7) # roll our die
count += 1
results[r] += 1
emp_percent = results[:]
for i in range(len(emp_percent)):
emp_percent[i] /= count
emp_percent[i] = round(emp_percent[i], 3)
if emp_percent == expected:
break
print(count)
print(emp_percent)
这里有几个问题。在
首先,不能保证这一点会永远终止,也不太可能在合理的时间内终止。忽略浮点运算问题,只有当您的数字分布正确时,才会终止。但是law of large numbers不能保证这种情况会发生。大数定律是这样的:
请注意,初始偏差是从不平衡。相反,它与其他结果相形见绌。这意味着偏差趋于零,但这不能保证偏差在有限的试验中消失。事实上,它特别预测,逐渐减少的偏见将继续无限期存在。所以这个算法永远不会终止是完全有可能的,因为总有那么一点点偏差仍然存在,统计上不重要,但仍然很大。在
这已经够糟糕的了,但是你也在使用浮点运算,浮点运算违反了很多传统的数学规则,因为计算机一直在进行中间舍入,以确保数字继续放入内存中,即使它们是重复的(以2为基数)或非理性的。事实上,你将经验百分位数四舍五入到小数点后三位并不能解决这个问题,因为并不是所有的终止小数(以10为基数)都是以二进制值结尾的(以2为基数),所以你可能仍然会发现经验值和预期值之间的不匹配。与其这样做:
…您可以尝试以下操作(仅在Python 3.5+中):
^{pr2}$这样可以同时解决这两个问题。默认情况下,^{} 要求值彼此之间的小数点后9位以内,因此它插入了必要的give,以便该算法能够实际工作。请注意,对于涉及零的比较,它确实需要特殊处理,因此您可能需要针对您的用例调整此代码,如下所示:
math.is_close()
也消除了取整你的经验的需要,因为它可以为你做这样的近似:如果您真的不想使用这些近似值,那么您将不得不放弃浮点,而只使用^{} 。它们被彼此分开时会产生精确的结果。但是,由于上面讨论的原因,您的算法不太可能很快终止(或者根本不可能终止)。在
与其尝试匹配浮点数,不如尝试为每个可能的和匹配期望值。这就相当于你试图做的事情,因为(观察数)/(试验次数)=(理论概率)当且仅当观察数等于预期数。当转鼓数是36的倍数时,这些值始终是整数。因此,如果转鼓的数量不是36的倍数,那么你的观察结果就不可能与期望值完全相等。在
要得到期望值,请注意,出现在各种和的确切概率中的分子(1,2,3,4,5,6,5,4,3,2,1分别为和2,3,…,12)中的分子是如果掷骰子36次,则是总和的期望值。如果骰子掷36i次,则将这些分子乘以i,得到期望的和值。下面的代码模拟将一对公平骰子重复掷36次,累计总计数,然后与预期计数进行比较。如果有一个完美匹配,则返回获得匹配所需的试验次数(其中一次试验为36轮)。如果
max_trials
没有发生这种情况,则给出一个表示最终计数与最终期望值之间差异的向量:以下是一些典型的输出:
^{pr2}$在一对公平骰子的3600万次模拟掷骰子中,不仅没有观察到准确的预期值,而且在最终状态下,观察值与期望值之间的差异变得相当大(在绝对值上,相对差异接近于零,正如大数定律预测的那样)。这种方法不太可能产生完美的匹配。一个可行的变化(同时仍然关注期望值)是迭代,直到观测值通过卡方拟合优度检验,与理论分布进行比较。在这种情况下,就没有理由再关注36的倍数了。在
相关问题 更多 >
编程相关推荐