根据用户名(id)和权重抽奖
package main
import (
"fmt"
"math/rand"
"time"
)
//return res[0]: userid, res[1]: weight
func GetRandomByWeight(m map[int64]int64, max_weight int64) (res [2]int64) {
rand.Seed(time.Now().UnixNano())
for uid, weight := range m {
r := rand.Int63n(max_weight) + 1
if r <= weight {
res[0] = uid
res[1] = weight
return res
}
}
return res
}
//生成指定数量的用户,并随机的给他们分配权重
func mock_user(user_count, max_weight int64) map[int64]int64 {
rand.Seed(time.Now().UnixNano())
m := make(map[int64]int64)
for i := int64(0); i < user_count; i++ {
m[i] = rand.Int63n(max_weight) + 1
}
return m
}
//测试模型是否正确,对10万用户抽奖1000万次,权重和中奖次数应该大致上成正比
func test_model() {
user_count := int64(100000)
max_weight := int64(20)
times := 10000000
weight_map := make(map[int64]int64)
mock_user := mock_user(user_count, max_weight)
//开始抽奖
begin := time.Now().Unix()
for i := 0; i < times; i++ {
tmp := GetRandomByWeight(mock_user, max_weight)
weight_map[tmp[1]] += 1
}
for i := int64(1); i < max_weight+1; i++ {
fmt.Println("权重:", i, "此权重中奖次数:", weight_map[i])
}
end := time.Now().Unix()
fmt.Println("用户数", user_count, ",抽奖", times, "次,耗时(秒):", end-begin)
}
func main() {
//验证模型是否可用
//test_model()
//模拟1亿用户抽奖,用户权重范围为1...10000
user_count := int64(100000000)
max_weight := int64(20)
mock_user := mock_user(user_count, max_weight)
//开始抽奖
begin := time.Now().UnixNano()
res := GetRandomByWeight(mock_user, max_weight)
end := time.Now().UnixNano()
fmt.Println("中奖用户ID:", res[0], "权重:", res[1], "抽奖耗时(纳秒):", end-begin)
}
test_model运行结果
权重: 1 此权重中奖次数: 49514
权重: 2 此权重中奖次数: 96324
权重: 3 此权重中奖次数: 144704
权重: 4 此权重中奖次数: 191649
权重: 5 此权重中奖次数: 239856
权重: 6 此权重中奖次数: 284260
权重: 7 此权重中奖次数: 319638
权重: 8 此权重中奖次数: 377491
权重: 9 此权重中奖次数: 431406
权重: 10 此权重中奖次数: 481927
权重: 11 此权重中奖次数: 522153
权重: 12 此权重中奖次数: 581450
权重: 13 此权重中奖次数: 628319
权重: 14 此权重中奖次数: 659269
权重: 15 此权重中奖次数: 706728
权重: 16 此权重中奖次数: 760366
权重: 17 此权重中奖次数: 814852
权重: 18 此权重中奖次数: 862671
权重: 19 此权重中奖次数: 903833
权重: 20 此权重中奖次数: 943590
用户数 100000 ,抽奖 10000000 次,耗时(秒): 110
为了更直观一点,做成表格:
图片4.png
1亿用户抽奖1次结果
中奖用户ID: 18163051 权重: 18 抽奖耗时(纳秒): 0