普通抽獎(jiǎng)問(wèn)題
問(wèn)題描述
用戶隨機(jī)抽獎(jiǎng),數(shù)據(jù)如下:
// map中,key代表用戶名,value代表成用戶下單數(shù)
var users map[string]int64 = map[string]int64{
"a": 10,
"b": 6,
"c": 3,
"d": 12,
"f": 1,
}
思路
隨機(jī)問(wèn)題,一般就是通過(guò)隨機(jī)函數(shù)從某個(gè)范圍內(nèi)隨機(jī)取出某個(gè)數(shù)值,則該數(shù)值對(duì)應(yīng)的就是中獎(jiǎng)用戶
在這里,如果我們能給map中每個(gè)元素設(shè)置對(duì)應(yīng)的索引,即轉(zhuǎn)化為數(shù)組,是不是就可以解決問(wèn)題了呢?
代碼實(shí)現(xiàn)
func GetAwardUserName(users map[string]int64) (name string) {
size := len(users)
awardIndex := rand.Intn(size)
i := 0
for userName, _ := range users {
if i == awardIndex {
name = userName
return
}
i++
}
return
}
單元測(cè)試
func Test_GetAwardUserName(t *testing.T) {
var users map[string]int64 = map[string]int64{
"a": 10,
"b": 6,
"c": 3,
"d": 12,
"f": 1,
}
rand.Seed(time.Now().Unix())
awardCount := make(map[string]int)
for i := 0; i <= 1000000; i++ {
awardName := GetAwardUserName(users)
if count, ok := awardCount[awardName]; ok {
awardCount[awardName] = count + 1
} else {
awardCount[awardName] = 0
}
}
for n, c := range awardCount {
fmt.Printf("%v:%v\n",n,c)
}
}
測(cè)試結(jié)果:
為了驗(yàn)證獲獎(jiǎng)概率的正確性,循環(huán)執(zhí)行100萬(wàn)次,每個(gè)用戶獲獎(jiǎng)的次數(shù)基本在20萬(wàn)左右,每個(gè)用戶的獲獎(jiǎng)概率相等
c:200102
f:199853
b:198942
a:200395
d:200704
權(quán)重抽獎(jiǎng)
問(wèn)題描述:
數(shù)據(jù)結(jié)構(gòu)和上面抽獎(jiǎng)問(wèn)題一致,只是這里,要求中獎(jiǎng)概率和用戶的訂單數(shù)成正比
思路
==本質(zhì)==還是隨機(jī)函數(shù)獲得一個(gè)數(shù)值,數(shù)值對(duì)應(yīng)的用戶即獲獎(jiǎng)用戶;這里要實(shí)現(xiàn)訂單數(shù)對(duì)獲獎(jiǎng)概率的影響問(wèn)題,即==訂單數(shù)對(duì)應(yīng)隨機(jī)數(shù)的某個(gè)范圍,訂單數(shù)越大,范圍越大,隨機(jī)數(shù)落在范圍內(nèi)的概率越大==
代碼實(shí)現(xiàn)
func getAwardUser_weight(users map[string]int64) (name string) {
type awardUser struct {
name string
offset int64
count int64
}
userSli := make([]*awardUser, 0,len(users))
var sumCount int64 = 0
for n, c := range users {
a := awardUser{
name: n,
offset: sumCount,
count: c,
}
//整理所有用戶的count數(shù)據(jù)為數(shù)軸
userSli = append(userSli, &a)
sumCount += c
}
awardIndex := rand.Int63n(sumCount)
for _, u := range userSli {
//判斷獲獎(jiǎng)index落在那個(gè)用戶區(qū)間內(nèi)
if u.offset+u.count>awardIndex {
name = u.name
return
}
}
return
}
單元測(cè)試
func Test_getAwardUser_weight(t *testing.T) {
var users map[string]int64 = map[string]int64{
"a": 10,
"b": 6,
"c": 3,
"d": 12,
"f": 1,
}
rand.Seed(time.Now().Unix())
awardCount := make(map[string]int)
for i := 0; i <= 100000; i++ {
awardName := getAwardUser_weight(users)
if count, ok := awardCount[awardName]; ok {
awardCount[awardName] = count + 1
} else {
awardCount[awardName] = 0
}
}
for n,c := range awardCount {
fmt.Printf("%v:%v \n",n,c)
}
}
測(cè)試結(jié)果:
循環(huán)遍歷了100萬(wàn)次,獲獎(jiǎng)的次數(shù),與用戶的訂單數(shù)成正比
c:93479
f:31206
d:375614
b:186933
a:312764
總結(jié)
解決實(shí)際問(wèn)題,往往都有數(shù)學(xué)模型去對(duì)應(yīng),比如抽獎(jiǎng)問(wèn)題,就可以轉(zhuǎn)化為初中所學(xué)習(xí)的數(shù)軸知識(shí),畫個(gè)草圖,簡(jiǎn)單易理解,也不需要多高深的數(shù)學(xué)知識(shí)
