Hello 大家好,我是鸭血粉丝,不知道你有没有过这样的经历,经常在手机上参与各种抽奖,但是明明眼看着就要中特等奖了,但是最后还是中了个谢谢参与,阿粉我就是一个中奖绝缘体,以前总是觉得是自己的运气不好,但是自从知道了背后的暗箱操作过后,阿粉就见怪不怪了。
背景
前段时间阿粉参与了一个活动的项目,这个项目有个功能就是在最后会有一个抽奖的页面,用户只要完成最后一步就能参与抽奖,并且奖品有 IPad 等大奖。但是大奖必定是有限制的,总不能无终止的让用户抽取,原本抽奖都是随机的,但是这种情况下肯定不能完全随机,因为要按照奖品的数量进行伪随机。
让数量多的小奖品更容易被抽中,数量少的大奖品被抽中的概率变小,那么在这种情况下,我们可以很自然的想到,我们需要给奖品增加一个权重来满足这个要求了。
设计
我们假设某次抽奖的奖品列表为”谢谢参与“,”50 元话费“,”200 元京东购物卡“,”Java 极客技术知识星球年卡一张“。然后因为经费有限,我们 50 元话费的名额为 100 个,200 元购物卡的 50 个,知识星球年卡 10 个,当然谢谢参与无限量。按照这种情况,我们就需要给每个奖品设置响应的权重值,假设我们这里这几个奖品对应的权重依次为 99,0.7,0.2,0.1,说明中谢谢参与的权重为 99,中年卡的权重为 0.1,为了方便计算我们这里将权重全部放大十倍,调整为 990,7,2,1。
思考
为了实现按照权重随机的效果,我们可以把权重想象成x 坐标轴上的位置,在 x 轴上标出每个奖品的范围,如下图所示:
从上图我们可以看出只要范围在 [0, 990) 的就说明中奖谢谢参与,同理 [990, 997) 表示中奖 50 元话费,[997, 999) 表示中奖 200 元京东购物卡,[999, 1000) 表示中奖知识星球年卡一张。
按照这种思路,我们只要随机生成一个数,然后看这个数在哪个范围里面,就能知道中的是什么奖品,而且这个中奖的比例也是跟权重正相关的。根据这个方案,我们需要记录这么几个数,一个是奖品 key,一个是权重 weight,一个是范围的最低值以及范围的最大值。
定义一个类用来存放上面提到的四个属性,如下
1 |
|
在定义一个使用的类
1 |
|
输出的结果:
1 |
|
通过输出的结果我们看到,基本是按照我们设置的权重进行随机的。通过上面的示例阿粉带大家设计了一个带权重的随机实现方案,除了在抽奖的场景会使用的,在其他类似的场景也可以使用。
参考
https://yq.aliyun.com/articles/269456
写在最后
最后邀请你加入我们的知识星球,这里有 1700+ 优秀的人与你一起进步,如果你是小白那你是稳赚了,很多业内经验和干活分享给你;如果你是大佬,那可以进来我们一起交流分享你的经验,说不定日后我们还可以有合作,给你的人生多一个可能。