用Python实现简单的抽奖程序

    科技2024-01-25  74

    抽奖基本需求

    1、假设中奖概率为:获得 a道具 10% b道具 20% c道具 30% d道具 40% 2、基本的想法是:生成1-100的连续数组,随机生成一个整数,如果是1-10 则中a、10-30 中b、30-60中c、60-100中d

    实现方法

    布尔判断

    1、第一种方法,直接判断数据在哪个范围,非常简单

    def choujiang0(): #生成一个1-100的随机整数 x = np.random.randint(0,100,dtype='int') if x>=0 and x<10: return 'a' if x>=10 and x<30: return 'b' if x>=30 and x<60: return 'c' if x>=60: return 'd'

    算法判断

    2、第二种方法:作为一个程序猿,不能满足于这种太简单的方法,不适合拓展嘛,所以想办法做改造下,用一个算法来实现抽奖,主要有以下两种方式: 2.1 把一个初始概率用字典来做配置,注意这里字典的键值是10、30、60、100,然后通过程序生成整数,判断这个整数落在区间里的概率,对应字典得到获得的奖励,以下是choujiang1方法:

    ratio = {10:'a',30:'b',60:'c',100:'d'} def choujiang1(): #生成一个1-100的随机整数 x = np.random.randint(1,101,dtype='int') #生成一个1-100的数组 mother = [x for x in range(1,101,1)] #判断x在数组的什么位置 x_position = mother.index(x) pre_number = 0 for key in ratio.keys(): if x_position - pre_number>=0 and x_position-int(key)<0: return ratio[key] if pre_number == 0: pre_number=int(key) return -1

    2.2 在第一点判断整理落在哪个区间的方法,有两种,第一种比较简单,通过for循环遍历字典,从数字0开始,如果满足大于等于前区间小于后区间,则直接读取字典值作为奖励,方法没问题,但次数多了这种遍历效率不高;第二种使用二分法,相对复杂一点,但是算法效率高一些,需要额外写一个二分法的递归方法search,来判断随机数值落在哪个区间,以下是search方法和choujiang2方法:

    search方法:

    #二分查询方法 def search(seq,number,lower=0,upper=None): if upper==None: upper = len(seq) - 1 #print('now lower is ',lower,' upper is ',upper) if upper==lower: #print('now lower is ',lower,' upper is ',upper) #assert number == seq[upper] return upper else: middle = (upper+lower)//2 if number>seq[middle]: #print('now lower is ',middle+1,' upper is ',upper) return search(seq,number,middle+1,upper) else: #print('now lower is ',lower,' upper is ',middle) return search(seq,number,lower,middle)

    choujiang2方法:

    #第二种抽奖方式 ratio = {10:'a',30:'b',60:'c',100:'d'} list_ratio = [] for i in ratio.keys(): list_ratio.append(i) list_ratio = sorted(list_ratio) def choujiang2(): #生成一个1-100的随机整数 x = np.random.randint(1,101,dtype='int') i = search(list_ratio,x,lower=0) key = list_ratio[i] return ratio[key]

    验证和效率

    如何验证

    验证一下概率是否符合我们的期望,代码如下:

    def test_choujiang(func,*args,**kwargs): Counter = {'a':0,'b':0,'c':0,'d':0} n = 1000000 for i in range(n): result = func(*args,**kwargs) for key in Counter.keys(): if result==key: Counter[key] += 1 print('a的概率是:{}'.format(Counter['a']/n)) print('b的概率是:{}'.format(Counter['b']/n)) print('c的概率是:{}'.format(Counter['c']/n)) print('d的概率是:{}'.format(Counter['d']/n)) %time test_choujiang(choujiang0)

    比较不同抽奖方法的效率

    采用二分法的抽奖方法,相对来说灵活性好且效率最高。

    %time test_choujiang(choujiang0) %time test_choujiang(choujiang1) %time test_choujiang(choujiang2)

    以下两次分别是10万次调用和100万次调用的时间顺序。

    #投10万次的结果 输出结果: a的概率是:0.1001 b的概率是:0.2028 c的概率是:0.29695 d的概率是:0.40015 Wall time: 820 ms a的概率是:0.10136 b的概率是:0.19901 c的概率是:0.29813 d的概率是:0.4015 Wall time: 2.7 s a的概率是:0.10018 b的概率是:0.20243 c的概率是:0.29917 d的概率是:0.39822 Wall time: 823 ms #投100万次的结果 输出结果: a的概率是:0.098874 b的概率是:0.199867 c的概率是:0.300063 d的概率是:0.401196 Wall time: 7.98 s a的概率是:0.10022 b的概率是:0.199958 c的概率是:0.300433 d的概率是:0.399389 Wall time: 17 s a的概率是:0.100109 b的概率是:0.200252 c的概率是:0.300102 d的概率是:0.399537 Wall time: 4.54 s
    Processed: 0.024, SQL: 8