Python Monty Hall 模拟给出了切换和不切换的相同几率

Python Monty Hall simulation giving equal odds for both switching and not

我在 Python 中创建了一个(相当复杂的)Monty Hall 模拟,但是,当 运行、return 时,对于 Switching 和 not,当我要知道,在现实中,这不可能,也不是这样。怎么了?

import math
import random

Right = 0
def TestWithSwitch():
    global Right
    wdoor = math.floor(random.random() * 3)
    doors = [0,0,0]
    doors[wdoor] = 1
    Ldoors = [0,0]
    i=0
    ##Declare winning door to be the winning door in the door Array

    for x in range(0, 3):
        if(x!=3):
            if(doors[x] != 1):
                Ldoors[i] = x
                i+=1
    ##Chose the losing doors to be the doors that aren't the winning door
    choice = math.floor(random.random() * 3)
    DoorOut = 0
    ##Pick a Choice
    LChose = False
    for y in range(0, 2):
        if(y!= 2):
            if(Ldoors[y] == choice):
                DoorOut = Ldoors[(y+1)%2]
                LChose = True
    if(LChose == False):
        DoorOut = Ldoors[math.floor(random.random() * 2)]
    Reserved = [DoorOut, choice]

##DoorOut is chosen from any of the losing doors we didn't pick as our choice, and is the door the computer is told doesn't have the prize
    for z in range(0, 3):
        if(z!= 3):
            if(z in Reserved == False):
                choice = z
                ##Make our new choice the other choice that we didn't previously choose
    if(choice == wdoor):
        Right+=1

def TestNoSwitch():
    global Right
    wdoor = math.floor(random.random() * 3)
    doors = [0,0,0]
    doors[wdoor] = 1
    Ldoors = [0,0]
    i=0


    for x in range(0, 3):
        if(x!=3):
            if(doors[x] != 1):
                Ldoors[i] = x
                i+=1
    choice = math.floor(random.random() * 3)
    if(choice == wdoor):
        Right+=1



for j in range(1, 10000):
    ## TestWithSwitch() and TestNoSwitch() both result in about 1/3. You can test by putting either function in.
    if(j == 9999):
        print(Right/10000)

我知道切换应该 return 66% 的几率,而不应该 return 33% 的几率。我收到的赔率加起来往往达不到 100%,但大约是三分之二,这在概率上是不可能的。

一方面,

for x in range(0, 3):
    if(x!=3):          # redundant: x will never be 3

另一方面,通过全局变量收集函数结果有点邪恶。

我会这样做:

from random import choice

DOORS = "ABC"

def pick():
    """
    Return a door at random
    """
    return choice(DOORS)

def always_switch():
    """
    Monty Hall strategy - when offered a choice, always switch
    """
    guess = pick()
    actual = pick()
    return not guess == actual

def never_switch():
    """
    Monty Hall strategy - when offered a choice, never switch
    """
    guess = pick()
    actual = pick()
    return guess == actual

def test(fn, tries):
    """
    Return the fraction of calls to fn which return True
    """
    return sum(1 for _ in range(tries) if fn()) / tries

def main():
    """
    Simulate the Monty Hall problem
    """
    tries = 10000

    pct = 100. * test(always_switch, tries)
    print("Test (always switch): %0.1f %%" % (pct,))

    pct = 100. * test(never_switch, tries)
    print("Test (never switch): %0.1f %%" % (pct,))

if __name__ == "__main__":
    main()

产生类似

的输出
Test (always switch): 66.3 %
Test (never switch): 32.7 %

注意:您可以通过任意将 guess = pick() 替换为 guess = "A" 来加快速度(不失一般性)。

问题在这里:

if(z in Reserved == False):

这被评估为 chained comparison,结果始终为 false。

if(z in Reserved and Reserved == False):

使用括号创建正确的运算符顺序:

if((z in Reserved) == False):

或者更好地使用显式 "not in" 运算符:

if(z not in Reserved):