为何我的蒙提霍尔问题模拟实现得出50%的概率?
问题分析与修复
你的代码核心问题出在切换门的逻辑上,导致有时候看似"换门",实际又换回了最初选择的门,最终拉平了胜率到50%。
具体bug点
你用这段代码来切换到另一扇门:
for k in doors: if k != choice: choice = k
当doors里只剩两扇门时,字典的遍历顺序(在Python 3.7之前是无序的,即使3.7+是插入有序,也可能出现遍历顺序覆盖的情况)会导致:
- 假设最初选择的门是
1,剩下的门是1和3 - 如果遍历顺序先到
3,choice会被改成3 - 接着遍历到
1,此时1 != 3,choice又被改回1
最终相当于没换门!这种情况随机发生,直接把胜率拉到了50%。
修复方案
替换掉遍历字典的换门逻辑,直接定位到另一扇门即可。比如用生成器表达式快速获取目标门:
# 替换原来的for循环 new_choice = next(k for k in doors if k != choice) choice = new_choice
或者把字典的键转成列表后直接取另一个元素:
door_keys = list(doors.keys()) choice = door_keys[0] if door_keys[1] == choice else door_keys[1]
额外优化点
你删除门的逻辑可以更高效:每次随机选门可能会重复选到已经删除的门,不如直接筛选出所有可以打开的门(不是用户选择、也没有车的门),再随机选一个删除:
# 导入random模块(比randint更灵活) import random # ...其他代码不变... while len(doors) > 2: # 直接筛选出所有符合主持人打开条件的门 possible_reveals = [door for door in doors if door != choice and doors[door] == "Donkey"] reveal = random.choice(possible_reveals) del doors[reveal]
修复后的完整代码
import random num_of_doors = 3 num_of_simulations = 0 wins = 0 while True: num_of_simulations += 1 # 初始化所有门为驴 doors = {k: "Donkey" for k in range(1, num_of_doors + 1)} # 随机放车 car_door = random.randint(1, num_of_doors) doors[car_door] = "Car" # 参赛者随机选门 choice = random.randint(1, num_of_doors) # 主持人打开多余的门,直到只剩2扇 while len(doors) > 2: possible_reveals = [door for door in doors if door != choice and doors[door] == "Donkey"] reveal = random.choice(possible_reveals) del doors[reveal] # 切换到另一扇门 new_choice = next(k for k in doors if k != choice) choice = new_choice # 统计获胜次数 if doors[choice] == "Car": wins += 1 # 打印当前胜率 print(f"当前胜率: {100 * wins / num_of_simulations:.2f}%")
运行这段代码,你会发现胜率逐渐趋近于2/3(约66.67%),符合蒙提霍尔问题的结论。
内容的提问来源于stack exchange,提问作者Anonymous Coder
相关产品推荐
相关产品推荐

