加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 大数据 > 正文

抽奖问题分析

发布时间:2020-12-16 18:06:18 所属栏目:大数据 来源:网络整理
导读:本文原创文章,转载注明出处,博客地址 https://segmentfault.com/u/to... 第一时间看后续精彩文章。觉得好的话,顺手分享到朋友圈吧,感谢支持。 普通抽奖问题 问题描述 用户随机抽奖,数据如下: // map中,key代表用户名,value代表成用户下单数var users map[s

本文原创文章,转载注明出处,博客地址 https://segmentfault.com/u/to... 第一时间看后续精彩文章。觉得好的话,顺手分享到朋友圈吧,感谢支持。

普通抽奖问题

问题描述

用户随机抽奖,数据如下:

// map中,key代表用户名,value代表成用户下单数
var users map[string]int64 = map[string]int64{
  "a": 10,"b": 6,"c": 3,"d": 12,"f": 1,}

思路

随机问题,一般就是通过随机函数从某个范围内随机取出某个数值,则该数值对应的就是中奖用户

在这里,如果我们能给map中每个元素设置对应的索引,即转化为数组,是不是就可以解决问题了呢?

代码实现

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
}

单元测试

func Test_GetAwardUserName(t *testing.T) {
    var users map[string]int64 = map[string]int64{
        "a": 10,}

    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:%vn",n,c)
    }
}

测试结果:

为了验证获奖概率的正确性,循环执行100万次,每个用户获奖的次数基本在20万左右,每个用户的获奖概率相等

c:200102
f:199853
b:198942
a:200395
d:200704

权重抽奖

问题描述:

数据结构和上面抽奖问题一致,只是这里,要求中奖概率和用户的订单数成正比

思路

本质还是随机函数获得一个数值,数值对应的用户即获奖用户;这里要实现订单数对获奖概率的影响问题,即订单数对应随机数的某个范围,订单数越大,范围越大,随机数落在范围内的概率越大

代码实现

func getAwardUser_weight(users map[string]int64) (name string) {
    userArr := make([]string,len(users),len(users))
    var sumCount int64 = 0
    index := 0
    for n,c := range users {
        //整理所有用户的count数据为数轴
        userArr[index] = n
        index++
        sumCount += c
    }

    awardIndex := rand.Int63n(sumCount)

    var offset int64
    for _,n := range userArr {
        //判断获奖index落在那个用户区间内
        offset += users[n]
        if offset > awardIndex {
            name = n
            return
        }
    }
    return
}

单元测试

func Test_getAwardUser_weight(t *testing.T) {
    var users map[string]int64 = map[string]int64{
        "a": 10,}

    rand.Seed(time.Now().Unix())
    awardCount := make(map[string]int)
    for i := 0; i <= 100000; i++ {
        awardName := getAwardUser_weight(users)
        if count,c := range awardCount {
        fmt.Printf("%v:%v n",c)
    }
}

测试结果:

循环遍历了100万次,获奖的次数,与用户的订单数成正比

c:93479 
f:31206 
d:375614 
b:186933 
a:312764

总结

解决实际问题,往往都有数学模型去对应,比如抽奖问题,就可以转化为初中所学习的数轴知识,画个草图,简单易理解,也不需要多高深的数学知识

问题本身并不难,重要的是转换思路,将抽象问题简化为具体的数学问题,然后去解决

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读