抽獎基本需求
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 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)
2、比較不同抽獎方法的效率
采用二分法的抽獎方法,相對來說靈活性好且效率最高。
%time test_choujiang(choujiang0) %time test_choujiang(choujiang1) %time test_choujiang(choujiang2) #投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