抽奖基本需求

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)
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]

验证和效率

1、如何验证

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

def test_choujiang(func,*args,**kwargs):
Counter= {'a':0,'b':0,'c':0,'d':0}
n= 1000000
for i inrange(n):
result= func(*args,**kwargs)for key inCounter.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)

2、比较不同抽奖方法的效率

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

%time test_choujiang(choujiang0)%time test_choujiang(choujiang1)%time test_choujiang(choujiang2)#投100万次的结果

输出结果:

a的概率是:0.098874b的概率是:0.199867c的概率是:0.300063d的概率是:0.401196Wall time:7.98s

a的概率是:0.10022b的概率是:0.199958c的概率是:0.300433d的概率是:0.399389Wall time:17s

a的概率是:0.100109b的概率是:0.200252c的概率是:0.300102d的概率是:0.399537Wall time:4.54 s