微信搶紅包演算法實現

2022-08-20 21:51:10 字數 4956 閱讀 7204

只討論金額隨機的情況,需要滿足規則:

所有人搶到金額之和要等於紅包總金額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 第二個 為保證第二個紅包...