抽獎(jiǎng)問(wèn)題分析

普通抽獎(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í)

image.png

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容