[恭喜发财]您有一个红包未领取
2018/12/08
耗时一天
事情源于要做英语演讲,思来想去,决定课题定为【微信红包】
无疑就是探究它的随机化和谁会拿到最多钱
为了方便的写好看的随机数,恶补了一天python(不用写分号和if while for后面跟着冒号让我十分不习惯
- 首先微信的红包金额不是在发布的时候分好的,而是当你打开的时候才进行计算的
原因可能是他们的程序员觉得这个操作太耗计算机资源吧(其实我觉得即使1s内有10000个人发了100个拼手气红包,服务器应该也还是吃得消的,毕竟应该服务器不会都是同一台吧
发现这个是因为,我在宿舍群里做了这么一个实验:当我发一个5分钱的红包时候,根据抽屉原理,我们寝室3个大佬和1个蒟蒻共4个人里必定有一个人会拿到2分钱
如果是发布的时候就计算好,应该能做到完全且均匀的随机分布,即每个人拿到2分钱的概率是一样的
但情况却是下图这样的:
连续5次,都是最后一个人拿到了2分钱!这个概率理应只有1/1024,但是现在却达到100%!
他一个人的收益达到了我们其他每个人收益总和的整整两倍
为了探究为什么这位大佬人品这么好,收益能达到我的两倍,我进行了反思
做了一些图表暗中观察
- 为了确保随机数是正常的,所以先测试一下python的随机数是不是分布均匀
这个表格是这样的,生成100000个[1,1000]的随机数,然后[1,10],[11,20],...,[990,1000]分组统计,横轴表示组编号,纵轴表示数量
通过图表可以看出,这个随机数分布得可谓是“前无古语言,后无来代码”的均匀且随机,实在是妙啊
- 言归正传,既然不是发布的时候分好金额,怎么做到在打开时计算又能均匀且随机呢
以我短浅的知识水平来说,这的确是挺难想出来的算法,大部分人的直觉应该是每次在剩余的金额里随机取一个值不就完事了
但这样其实做不到均匀
为了能直观表现出到底有多么不均匀,我写了个python程序让它给30个人以这种规则分别发10,100,1000,100000次红包,统计每个人获得的金额总和,情况大概是这样的
基本上第7个以后的人这辈子都是无产阶级了,而勤奋的人【或者勤奋=手快】可以成为高产阶级了,坐拥百万不是梦
看起来这个算法是不行的,那么该怎么做呢?
对于刚幼儿园毕业12年的不懂算法的我来说,当然是去网上找现成的算法了
- 有位不愿意透露姓名的微信员工说“这不是很简单嘛,你只要这样这样,最后biu一下就均匀了嘛”
事情是这样的: 你获得的钱=在[0.01,剩下钱*2/剩下红包个数)这个区间里的一个随机数
得知这个消息的我十分激动,于是我去吃了午饭,咳,于是我写了一个c++程序用来检验我能找得到的一些正常的红包数据,结果发现的确每个红包都符合这条规则
然后我写了个python程序来生成这样的红包,同样分给30个人抢,然后绘制了 从发1次到100000次红包每个人获得的金额平均值阶梯图表
现场十分的热闹:
也就是说,根据这个算法,当你抢了很多次红包以后,不论你每次是第几个抢到红包的,最终抢到的总金额都是差不多的
但是终究不是发布的时候就随机的,于是乎,它应该有一些神奇的地方是没有变成随机且均匀的
- 方差
我最先能想到的就是它的方差,当它大于1次以后,数据变化的波动大小能不能均匀呢?于是我继续用刚刚的python程序生成数据,然后又写了一个c++程序对数据进行方差计算,绘制成图表后如下:
当发红包次数变多时,达到1000次以上时,趋势变得明显了
简言之:如果你每次都是最后几个抢到红包的,那么你每次拿到的红包金额大小会差别很大,而如果你每次都是手速快的那几个,那么你每次拿到钱的金额大小并不会差很多。
- 手气最佳次数
最后是大家最关心的,到底怎么抢比较好抢到手气最佳呢?
我按阶梯数据统计了每个人拿到手气最佳的次数,再次绘制成图表【嗯,我还学会了如何制图表,做到恶心
当数据小的时候,看似还能随机分布,但是当发红包次数达到1000次以上时,后面抢到红包的人开始吃香了,他们因为方差大而较有可能拿到面额大的红包,故手气最佳的次数相对也就上去了
结论就是:下一次你看到红包的时候,别急,不妨去喝个茶撸个猫什么的,等你回来的时候再抢,也许
红包就被抢完了!!!!
-- 于 ,共写了1691个字;
-- 文内使用到的标签:
- 下一篇:【noip杂记】
- 上一篇:学习2019搜索引擎使用情况报告
学习了学习了