由久赌必输引发的思考

发布于 2020-07-31  14 次阅读


开端

前几天和同学讨论赌博中的数学,然后看了李永乐老师的视频,知道了久赌必输的数学原理,于是我灵机一动,不用数学知识直接用计算机模拟获得大概结果会咋样呢,于是作为新手的我造了一下午的轮子,下面是造的辣鸡轮子

原始代码

import random,datetime

def rand_sort(rand_list):#为啥不用shuffle呢,因为轮子要自己造
    swap_index=tem=0
    for i in range(len(rand_list),0,-1):
        swap_index=random.randint(0,i-1)
        tem=rand_list[i-1]
        rand_list[i-1]=rand_list[swap_index]
        rand_list[swap_index]=tem
    return rand_list

def app_target():#运算函数
    global PR_list
    for i in range(10000):
        user_money=input_user_money
        PR_list=rand_sort(PR_list)
#上面这句增加随机度,实测可以不用这个也能得到类似正确答案并且差距不大,前辈们写的代码果然厉害
        while True:       
            user_money+=single_money*PR_list[random.randint(0,len(PR_list)-1)]
            if user_money=user_target:
                good.append(1)
                break

PR_list=[]
good=[]
bad=[]
q=0
PR=int(input('请输入概率:'))
input_user_money=int(input('请输入你的本金:'))
single_money=int(input('请输入赌注:'))
user_target=int(input('请输入你的目标:'))
start_t = datetime.datetime.now()
for i in range(100):#得到n/100的概率
    if i< PR:
        PR_list.append(1)
    else:
        PR_list.append(-1)
app_target()
end_t = datetime.datetime.now()
print('经过10000次模拟你可以达到预期的概率约为',len(good)/100)
spendtime = (end_t - start_t).total_seconds()
print("本次运算共消耗:{:.2f}秒".format(spendtime))

示例输入

请输入概率:50
请输入你的本金:100
请输入赌注:1
请输入你的目标:120
经过10000次模拟你可以达到预期的概率约为 83.52
本次运算共消耗:21.11秒

python多核优化

和视频示例算出的结果5/6极其接近了,但是这10000次运算时间也太久了吧,一看python进程cpu才占用了不到20%(我的cpu是
i5 9400 6C/6T)一搜知道这是由于全局解释器锁(GIL)导致无法完美使用多核资源,于是我东拼西凑凑出了一套可以使用多核资源的代码

import random,datetime,os
from multiprocessing import Process,Manager,Pool
def rand_sort(rand_list):
    swap_index=tem=0
    for i in range(len(rand_list),0,-1):
        swap_index=random.randint(0,i-1)
        tem=rand_list[i-1]
        rand_list[i-1]=rand_list[swap_index]
        rand_list[swap_index]=tem
    return rand_list

def app_target(good,bad,PR,input_user_money,single_money,user_target,PR_list,name):

    print('开始进程:{},这是{}'.format(os.getpid(),name))
    for i in range(2500):
        user_money=input_user_money
        PR_list=rand_sort(PR_list)
        while True:       
            user_money+=single_money*PR_list[random.randint(0,len(PR_list)-1)]
            if user_money=user_target:
                good.append(1)
                break
    print('进程{}结束'.format(name))


if __name__ =='__main__':
    mg = Manager()
    good=mg.list()
    bad=mg.list()
    PR_list=[]
    p = Pool(4)
    PR=int(input('请输入概率:'))
    input_user_money=int(input('请输入你的本金:'))
    single_money=int(input('请输入赌注:'))
    user_target=int(input('请输入你的目标:'))
    start_t = datetime.datetime.now()
    for i in range(100):
        if i< PR:
            PR_list.append(1)
        else:
            PR_list.append(-1)
    for name in ['Thread1','Thread2','Thread3','Thread4']:
        p.apply_async(app_target,(good,bad,PR,input_user_money,single_money,user_target,PR_list,name))
    print('等待所有进程启动完毕...')
    p.close()
    p.join()
    end_t = datetime.datetime.now()
    print('经过',len(good)+len(bad),'次模拟你可以达到预期的概率约为',len(good)*100/(len(good)+len(bad)),'%')
    spendtime = (end_t - start_t).total_seconds()
    print("本次运算共消耗:{:.2f}秒".format(spendtime))

示例输入

请输入概率:50
请输入你的本金:100
请输入赌注:1
请输入你的目标:120
等待所有进程启动完毕...
开始进程:10072,这是Thread1
开始进程:508,这是Thread3
开始进程:13896,这是Thread4
开始进程:11980,这是Thread2
进程Thread1结束
进程Thread4结束
进程Thread3结束
进程Thread2结束
经过 10000 次模拟你可以达到预期的概率约为 83.29 %
本次运算共消耗:5.43秒

可以看出使用了4个线程之后速度快了四倍


本当の声を響かせてよ