Skip to main content
 首页 » 编程设计

python之更有效地模拟 2 个骰子之Python

2025年05月04日59小虾米

我编写了一个程序来记录需要掷多少次 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不保证这会发生。大数定律是这样运作的:

  1. 您的初步结果几乎肯定(随机)以某种方式存在偏差。
  2. 最终,尚未进行的试验数量将大大超过您最初的试验数量,而这些后来的试验中缺乏偏倚将超过您最初的偏倚。

请注意,初始偏差永远不会被抵消。相反,它与其他结果相比相形见绌。这意味着偏差趋于零,但它并不能保证偏差在有限次数的试验中确实消失。事实上,它明确预测,越来越小的偏见将无限期地继续存在。因此,该算法永远完全有可能终止,因为始终存在微小的偏差,在统计上微不足道,但仍然存在。

这已经够糟糕了,但您还在使用 float ,has its own issues ;特别是,浮点运算违反了许多传统的数学规则,因为计算机不断进行中间舍入以确保数字继续适合内存,即使它们是重复的(以 2 为底)或无理数。您将经验百分比四舍五入到小数点后三位的事实实际上并不能解决这个问题,因为并非所有终止小数(基数 10)都是终止二进制值(基数 2),因此您可能仍然会发现经验值和预期值之间不匹配.而不是这样做:

if emp_percent == expected: 
    break 

...您可以试试这个(仅限 Python 3.5+):

if all(map(math.is_close, emp_percent, expected)): 
    break 

这同时解决了这两个问题。默认情况下,math.is_close()要求值彼此相差(大约)9 位小数,因此它为该算法插入了必要的条件,使其真正有机会工作。请注意,它确实需要对涉及零的比较进行特殊处理,因此您可能需要针对您的用例调整此代码,如下所示:

is_close = functools.partial(math.is_close, abs_tol=1e-9) 
if all(map(is_close, emp_percent, expected)): 
    break 

math.is_close() 还消除了对您的经验进行舍入的需要,因为它可以为您做这个近似:

is_close = functools.partial(math.is_close, rel_tol=1e-3, abs_tol=1e-5) 
if all(map(is_close, emp_percent, expected)): 
    break 

如果您真的不想要这些近似值,您将不得不放弃浮点并使用 fractions只。当彼此相除时,它们会产生精确的结果。但是,由于上述原因,您仍然会遇到算法不太可能快速终止(或可能根本不会终止)的问题。