只討論金額隨機的情況,需要滿足規則:
所有人搶到金額之和要等於紅包總金額1. 每個人至少搶到一分錢1. 要保證所有人搶到金額的機率相等方案一:每個人點進來領,金額隨機,隨機的上限是當前剩餘的紅包金額。每次搶到的金額 = 隨機區間(0,剩餘紅包金額)
分析:這樣做的缺陷是越早領越有優勢,因為每次搶到的金額 = 隨機區間(0,剩餘金額),越早搶能領到的平均金額越大。假設有 10 個人,紅包總金額 100,第乙個人的隨機範圍是(0,100),平均金額 = 50;假設第乙個人隨機到 50 元,第二個人的隨機範圍就是(0,50),平均金額 = 25;假設第二個人隨機到 25 元,第三個人的隨機範圍就是(0,25),平均金額 = 12.5;以此類推,每一次的隨機範圍越來越小,平均金額也越小。
方案二:二倍均值法。設剩餘紅包金額為 m,剩餘人數為 n,每次搶到的金額 = 隨機區間(0,m / n * 2)。
分析:這樣保證了每個隨機金額的平均值是相等的,不會因為搶紅包的先後順序而造成不公平。假設有 10 個人,紅包總金額 100,第乙個人的隨機範圍是(0,100/10 2)=(0,20),平均金額 = 10;假設第乙個人隨機到 10 元,第二個人的隨機範圍就是(0,90/9 2)=(0,20),平均金額 = 10;假設第二個人隨機到 10 元,第三個人的隨機範圍就是(0,80/8 * 2)=(0,20),平均金額 = 10。以此類推,每一次的隨機範圍都相同,平均值也相同。二倍均值法保證了搶紅包的公平性,但不能保證真正的隨機性。因為除了最後乙個人,前面任何乙個人搶到的金額都一定小於當前人均金額的兩倍,並不是真正的隨機。
python **實現:
import random
def getpacket(amount, nums):
limit = round(amount / nums * 2, 2) # 求取上限(0,m / n * 2)
print('隨機金額範圍:({}, {})'.format(0, limit))
cur = round(random.uniform(0, limit), 2)
return cur
if __name__ == '__main__':
amount, nums = 100, 10
cur_num = nums
send = 0
for i in range(cur_num):
if i == nums-1:
reward = amount
else:
reward = getpacket(amount, cur_num)
amount = round(amount - reward, 2)
send = round(send + reward, 2)
cur_num -= 1
print('第 {} 個人:{} 元'.format(i+1, reward))
print('剩餘金額:{} 元'.format(amount))
print('已被領取:{} 元'.format(send))
print('--------------------')
>>>
隨機金額範圍:(0, 20.0)
第 1 個人:0.32 元
剩餘金額:99.68 元
已被領取:0.32 元
--------------------
隨機金額範圍:(0, 22.15)
第 2 個人:20.5 元
剩餘金額:79.18 元
已被領取:20.82 元
--------------------
隨機金額範圍:(0, 19.8)
第 3 個人:8.3 元
剩餘金額:70.88 元
已被領取:29.12 元
--------------------
隨機金額範圍:(0, 20.25)
第 4 個人:10.25 元
剩餘金額:60.63 元
已被領取:39.37 元
--------------------
隨機金額範圍:(0, 20.21)
第 5 個人:7.01 元
剩餘金額:53.62 元
已被領取:46.38 元
--------------------
隨機金額範圍:(0, 21.45)
第 6 個人:11.42 元
剩餘金額:42.2 元
已被領取:57.8 元
--------------------
隨機金額範圍:(0, 21.1)
第 7 個人:15.78 元
剩餘金額:26.42 元
已被領取:73.58 元
--------------------
隨機金額範圍:(0, 17.61)
第 8 個人:0.9 元
剩餘金額:25.52 元
已被領取:74.48 元
--------------------
隨機金額範圍:(0, 25.52)
第 9 個人:8.11 元
剩餘金額:17.41 元
已被領取:82.59 元
--------------------
第 10 個人:17.41 元
剩餘金額:0.0 元
已被領取:100.0 元
--------------------
方案三:生成 k 個隨機數,k 等於設定的分紅包人數,保證 k 個隨機數的和為 1,用總金額分別去乘這 k 個比例值,即可得到隨機金額的 k 個紅包,保證公平性和隨機性。
import random
def getpacketratio(nums):
rand = [random.uniform(0, 5) for _ in range(nums)]
sum = 0
for i in range(nums):
sum += rand[i]
for i in range(nums):
rand[i] = rand[i] / sum
return rand
if __name__ == '__main__':
amount, nums = 100, 10
cur_amount, cur_num = amount, nums
ratio = getpacketratio(nums)
#print(sum(ratio))
send = 0
for i in range(cur_num):
if i == nums-1:
reward = cur_amount
else:
#print('ratio = ', ratio[i])
reward = round(amount * ratio[i], 2)
cur_amount = round(cur_amount - reward, 2)
send = round(send + reward, 2)
print('第 {} 個人:{} 元'.format(i+1, reward))
print('剩餘金額:{} 元'.format(cur_amount))
print('已被領取:{} 元'.format(send))
print('--------------------')
>>>
ratio = 0.027962885102786654
第 1 個人:2.8 元
剩餘金額:97.2 元
已被領取:2.8 元
--------------------
ratio = 0.009667867723838998
第 2 個人:0.97 元
剩餘金額:96.23 元
已被領取:3.77 元
--------------------
ratio = 0.11110828265475124
第 3 個人:11.11 元
剩餘金額:85.12 元
已被領取:14.88 元
--------------------
ratio = 0.0600812043281718
第 4 個人:6.01 元
剩餘金額:79.11 元
已被領取:20.89 元
--------------------
ratio = 0.37838480938749
第 5 個人:37.84 元
剩餘金額:41.27 元
已被領取:58.73 元
--------------------
ratio = 0.13730146852600614
第 6 個人:13.73 元
剩餘金額:27.54 元
已被領取:72.46 元
--------------------
ratio = 0.1592426133137283
第 7 個人:15.92 元
剩餘金額:11.62 元
已被領取:88.38 元
--------------------
ratio = 0.09194720453033237
第 8 個人:9.19 元
剩餘金額:2.43 元
已被領取:97.57 元
--------------------
ratio = 0.008397562213245897
第 9 個人:0.84 元
剩餘金額:1.59 元
已被領取:98.41 元
--------------------
第 10 個人:1.59 元
剩餘金額:0.0 元
已被領取:100.0 元
--------------------
微信搶紅包架構設計
實時性 為什麼明明搶到紅包,點開後發現沒有?答 2014年的紅包一點開就知道金額,分兩次操作,先搶到金額,然後再轉賬。2015年的紅包的拆和搶是分離的,需要點兩次,因此會出現搶到紅包了,但點開後告知紅包已經被領完的狀況。進入到第乙個頁面不代表搶到,只表示當時紅包還有。分配 紅包裡的金額怎麼算?為什麼...
如何實現搶紅包演算法?
方法一 二倍均值法 public static listdivideredpackage integer totalamount,integer totalpeoplenum amountlist.add restamount return amountlist 缺陷 除了最後一次,任何一次搶到的金...
PHP實現微信紅包演算法和微信紅包的架構設計簡介
使用php發紅包,當我們輸入紅包數量和總金額後,php會根據這兩個值進行隨機分配每個金額,保證每個人都能領取到乙個紅包,每個紅包金額不等,就是要求紅包金額要有差異,所有紅包金額總額應該等於總金額。設定總金額為10元,有n個人隨機領取 n 1 第乙個 則紅包金額 x元 n 2 第二個 為保證第二個紅包...