有趣的概率——车羊问题、硬币问题、博弈问题

 1、经典车羊问题

假设你参加一个游戏节目,有三扇关闭的门,其中一扇后面有一辆汽车,而其他两扇后面是山羊。你首先选择一扇门,然后主持人打开另外两扇门中的一扇,露出其中一只山羊。

现在,你可以选择是否改变自己的选择,选择另外一扇未被打开的门。那么,应该改变选择还是保持原来的选择呢?

import random

def monty_hall_simulation(change_choice, num_trials):
    wins_times = 0
    
    for _ in range(num_trials):
        doors = ['car', 'goat', 'goat']
        random.shuffle(doors)  # 随机排列门的位置        
        first_selected_door = random.randint(0, 2)  # 随机选择一扇门
        
        # 主持人打开一扇有山羊的门
        opened_door = next(i for i in range(3) if i != first_selected_door and doors[i] == 'goat')
#判断是否选择交换
if change_choice: selected_door = next(i for i in range(3) if i not in (first_selected_door, opened_door)) else: selected_door = first_selected_door if doors[selected_door] == 'car': wins_times += 1 win_percentage = (wins_times / num_trials) * 100 return win_percentage # 进行10000次实验 win_percentage_with_change= monty_hall_simulation(change_choice=1, num_trials=10000) win_percentage_without_change= monty_hall_simulation(change_choice=0, num_trials=10000) print(f"改变选择时获胜的概率: {win_percentage_with_change}%") print(f"保持选择时获胜的概率: {win_percentage_without_change}%") #输出 改变选择时获胜的概率: 66.25% 保持选择时获胜的概率: 33.22%

2、假如我有初始筹码一百块钱,现在有个抛硬币的游戏,抛出正反面的概率是0.5,每次抛出正面,我的筹码量可以增加80%,抛出反面则减少50%,那么我该玩这个游戏吗?

 2.1 如果每次必须all in,则不玩,玩的越多赢钱概率越低,假如每次赢钱增加比例p,每次输钱后亏损比例为q,若(1+p)*(1-q)<1,则不该玩,学过极限的朋友知道,小于1的分数的n次方的极限等于0,有些看起来胜率为0.5的游戏其实是必输的,例如赌场的赌大小,会因为一点点的抽水使得重复n次后变成理论上必输的游戏

def get_res(num_trials):
    x=100

    for _ in range(num_trials):
        if func_p(0.5) == 1:
            x=x*1.8
        else:
            x=x*0.5
    return x

res=get_res(100000)

print ("最终收益为:"+str(res-100))
#输出
#最终收益为:-100.0

 2.1 如果可以改变筹码量,则可以玩,假如每次赢钱增加比例p,每次输钱后亏损比例为q,虽然(1+p)*(1-q)<1,例如p=0.8,q=0.5,1.8*0.5=0.1<1,因为可以改变筹码量,但是每次赢钱的期望为本金*(p-q)/2 ,只要p>q,就可以玩

 

#单次抛硬币后我筹码的期望为0.5*180+0.5*50=115,只要有充足的资金,不管玩几次,单次的期望始终为正值
def
get_res(num_trials): res=0 for _ in range(num_trials): x=100 #每次筹码量固定 if func_p(0.5) == 1: x=x*1.8 else: x=x*0.5 res=res+x return (res/num_trials) res=get_res(100000) print ("平均收益为:"+str(res-100)) #输出 #平均收益为:15.092299999999994

 

3、一帅哥在酒吧里喝酒,一美女走来邀请玩游戏,规则是,每人手里拿一个硬币,自己选择正面或者反面,然后扣在桌子上,然后同时把手拿开,如果两个硬币都是正面,美女要给帅哥3块钱,两个都是反面,美女要给帅哥1块钱,如果一正一反,则帅哥要给美女2块钱,男女双方均可以控制自己出正反面的频率,如果你是这个帅哥,你玩吗?

期望看似是E= (1/4)*-3+(1/2)*2+(1/4)*-1 = 0 ,如果两人都是随机出的话,期望确实为0,有没有一种策略,不管帅哥怎么玩,只要他没有读心术,玩多了一定输钱呢?

假设帅哥出正面的频率为X ,出反面的频率为1-X,美女正面的频率为Y ,出反面的频率为1-Y,则帅哥赢钱的期望为 3XY +(-2)*(1-X)*Y+(-2)*(1-Y)*X+(-1)*(1-X)*(1-Y) =8XY-3X-3Y+1。美女如果想让帅哥亏钱,则必须找到一个Y,不管X等于0到1的任何值,使得8XY-3X-3Y+1恒小于0,经计算 1/3<Y<2/5 即可满足条件,即如下图等高线中红框部分

# 激活交互式图形
%matplotlib notebook
import numpy as np
import matplotlib.pyplot as plt

# 定义 x 和 y 的范围
x = np.linspace(0, 1, 100)
y = np.linspace(0, 1, 100)

# 创建网格点坐标矩阵
X, Y = np.meshgrid(x, y)

# 计算相应的 z 值
Z = 8 * X * Y - 3 * X - 3 * Y + 1
# 创建等高线图
plt.contour(X, Y, Z, levels=[0], colors='blue')
# 绘制曲面
plt.imshow(Z, extent=(0, 1, 0, 1), origin='lower', cmap='viridis', alpha=0.3)
plt.colorbar(label='z')

# 设置坐标轴标签
plt.xlabel('x')
plt.ylabel('y')

# 显示图形
plt.show()

 

 

def get_e(x,y,num_trail):
    l=0

    for _ in range(num_trail):
        res1 =  func_p(x)
        res2 =  func_p(y)
    
        if res1 == res2 == 1:
            s=3
        elif (res1 == 0 and res2== 1) or (res1 == 1 and res2== 0) :
            s= -2
        elif res1 == res2 == 0:
            s=1
        l=l+s
    return l

res=get_e(0.1,11/30,1000000)
print ("玩一百万次后帅哥赢钱为:"+str(res))

#输出 -105832

 

posted @ 2023-10-11 15:58  glowwormss  阅读(103)  评论(0编辑  收藏  举报