别人在抢红包,程序员在研究红包算法
创始人
2025-01-10 17:41:41
0次

微信红包在羊年春节的火爆程度不言而喻,广告主投入5亿现金红包,与央视羊年春晚独家合作起到了巨大的推动作用。这就像一针大补丸,在短时间内给微信带来了极大的关注度与流量。除夕全天微信用户红包总发送量达到10.1亿次,摇一摇互动量达到110亿次,红包峰值发送量为8.1亿次/分钟。

抛开微信红包的市场价值不谈,红包本身的算法也引发了热议,由于官方没有给出明确的说法,各家也是众说纷纭,小编下面也为大家带来几种分析。

首先看看数据分析帝

大多数人都做出自己的猜测,这也是在不知道内部随机算法的时候的唯一选择,但是大多数人没有给出自己亲自的调查结果。这里给出一份100样本的调查抽样样本数据,并提出自己的猜测。

1. 钱包钱数满足截尾正态随机数分布。大致为在截尾正态分布中取随机数,并用其求和数除以总价值,获得修正因子,再用修正因子乘上所有的随机数,得到红包价值。

这种分布意味着:低于平均值的红包多,但是离平均值不远;高于平均值的红包少,但是远大于平均值的红包偏多。

图1. 钱包价值与其频率分布直方图及其正态拟合

但看分布直方图并不能推出它符合正态分布,但是考虑到程序的简洁性和随机数的合理性,这是最合乎情理的一种猜测。

 越是后面的钱包,价值普遍更高

图2. 钱包序列数与其价值关系曲线

从图2中的线性拟合红线可以看到,钱包价值的总体变化趋势是在慢慢增大,其变化范围大约是一个绿色虚线上下界划出的“通道”。(曲线可以被围在这么一个正合乎常规的“通道”中,也从侧面反映了规律1的合理性,说明了并不是均匀分布的随机数)

从另一个平均数的图中也可以看出这一规律。

图3. 平均数随序列数的变化曲线

在样本中,1000价值的钱包被分成100份,均值为10。然而在图3中我们可以看到在***一个钱包之前,平均数一直低于10,这就说明了一开始的钱包价值偏低,一直被后期的钱包价值拉着往上走,后期的钱包价值更高。

3. 当然平均数的图还可以透露出另一个规律,那就是***的那一个人往往容易走运抽得比较多。因为***那一个人是钱包剩下多少就拿多少的,而之前所有人的平均数 都低于10,所以至少保证了***一个人会高于平均值。在本样本中,98号钱包抽到35,而***一份钱包抽到46。

综上,根据样本猜测:

1. 抽到的钱大多数时候跟别人一样少,但一旦一多,就容易多很多。

2. 越是抽后面的钱包,钱越容易多。

3. ***一个人往往容易撞大运。

点评:这种明显很实际有差异,小编每次不管什么时候抢都是几毛钱。

第二位同学写了一个简单python 代码

据观察,红包分钱满足以下几点:

1.不会有人拿不到钱

2.不会提前分完

3.钱的波动范围很大

红包在一开始创建的时候,分配方案就订好了。抢红包的时候,不过是挨个pop up而已。

因此 python 代码如下:

  1. def weixin_divide_hongbao(money, n): 
  2. divide_table = [random.randint(1, 10000) for x in xrange(0, n)] 
  3. sum_ = sum(divide_table) 
  4. return [x*money/sum_ for x in divide_table] 

不过上述算法还有两个小问题:

1.浮点数精度问题

2.边界值的处理

第三位同学按照网上流传的python写了一个java的版本

  1. int j=1; 
  2. while(j<1000) 
  3. { 
  4. int number=10; 
  5. float total=100; 
  6. float money; 
  7. double min=0.01; 
  8. double max; 
  9. int i=1; 
  10.  
  11. List math=new ArrayList(); 
  12. while(i
  13. { 
  14.  
  15. max = total- min*(number- i); 
  16. int k = (int)((number-i)/2); 
  17. if (number -i <= 2) 
  18. {k = number -i;} 
  19. max = max/k; 
  20. money=(int)(min*100+Math.random()*(max*100-min*100+1)); 
  21. money=(float)money/100; 
  22. total=total-money; 
  23. math.add(money); 
  24. System.out.println("第"+i+"个人拿到"+money+"剩下"+total); 
  25. i++; 
  26. if(i==number) 
  27. { 
  28. math.add(total); 
  29. System.out.println("第"+i+"个人拿到"+total+"剩下0"); 
  30. } 
  31. } 
  32.  
  33. System.out.println("本轮发红包中第"+(math.indexOf(Collections.max(math))+1)+"个人手气***"); 
  34. j++; 
  35. } 

第四位同学的这种算法看起来非常科学。

他认为:

1、每个人都要能够领取到红包;

2、每个人领取到的红包金额总和=总金额;

3、每个人领取到的红包金额不等,但也不能差的太离谱,不然就没趣味;

4、算法一定要简单,不然对不起腾讯这个招牌;

正式编码之前,先搭建一个递进的模型来分析规律

设定总金额为10元,有N个人随机领取:

N=1

则红包金额=X元;

N=2

为保证第二个红包可以正常发出,***个红包金额=0.01至9.99之间的某个随机数

第二个红包=10-***个红包金额;

N=3

红包1=0.01至0.98之间的某个随机数

红包2=0.01至(10-红包1-0.01)的某个随机数

红包3=10-红包1-红包2

……

  1. header("Content-Type: text/html;charset=utf-8");//输出不乱码,你懂的 
  2. $total=10;//红包总额 
  3. $num=8;// 分成8个红包,支持8人随机领取 
  4. $min=0.01;//每个人最少能收到0.01元 
  5.  
  6. for ($i=1;$i<$num;$i++) 
  7. { 
  8.     $safe_total=$total-($num-$i)*$min;//随机安全上限 
  9.     $money=mt_rand($min*100,$safe_total*100)/100; 
  10.     $total=$total-$money; 
  11.     echo '第'.$i.'个红包:'.$money.' 元,余额:'.$total.' 元 
    '; 
  12. } 
  13. echo '第'.$num.'个红包:'.$total.' 元,余额:0 元'; 

输入一看,波动太大,这数据太无趣了!

第1个红包:7.48 元,余额:2.52 元

第2个红包:1.9 元,余额:0.62 元

第3个红包:0.49 元,余额:0.13 元

第4个红包:0.04 元,余额:0.09 元

第5个红包:0.03 元,余额:0.06 元

第6个红包:0.03 元,余额:0.03 元

第7个红包:0.01 元,余额:0.02 元

第8个红包:0.02 元,余额:0 元

改良一下,将平均值作为随机安全上限来控制波动差

  1. header("Content-Type: text/html;charset=utf-8");//输出不乱码,你懂的 
  2. $total=10;//红包总额 
  3. $num=8;// 分成8个红包,支持8人随机领取 
  4. $min=0.01;//每个人最少能收到0.01元 
  5.  
  6. for ($i=1;$i<$num;$i++) 
  7. { 
  8.     $safe_total=($total-($num-$i)*$min)/($num-$i);//随机安全上限 
  9.     $money=mt_rand($min*100,$safe_total*100)/100; 
  10.     $total=$total-$money; 
  11.     echo '第'.$i.'个红包:'.$money.' 元,余额:'.$total.' 元 
    '; 
  12. } 
  13. echo '第'.$num.'个红包:'.$total.' 元,余额:0 元'; 

输出结果见下图

第1个红包:0.06 元,余额:9.94 元

第2个红包:1.55 元,余额:8.39 元

第3个红包:0.25 元,余额:8.14 元

第4个红包:0.98 元,余额:7.16 元

第5个红包:1.88 元,余额:5.28 元

第6个红包:1.92 元,余额:3.36 元

第7个红包:2.98 元,余额:0.38 元

第8个红包:0.38 元,余额:0 元

小结:

小编觉得这完全可以理解成一个红包引发的血案,小编仅仅列举了几个,还有一些工程学的同学直接抛出了数学模型、离散函数等等,但是无论算法是简单还是复杂,玩的开心就够了。

相关内容

热门资讯

PHP新手之PHP入门 PHP是一种易于学习和使用的服务器端脚本语言。只需要很少的编程知识你就能使用PHP建立一个真正交互的...
网络中立的未来 网络中立性是什... 《牛津词典》中对“网络中立”的解释是“电信运营商应秉持的一种原则,即不考虑来源地提供所有内容和应用的...
各种千兆交换机的数据接口类型详... 千兆交换机有很多值得学习的地方,这里我们主要介绍各种千兆交换机的数据接口类型,作为局域网的主要连接设...
粉嫩如何诠释霸道 东芝M805... “霸道粉”是个什么玩意东芝M805拿过来的时候,笔者扑哧笑了,不是笑这款笔记本,而是笑这款产品的颜色...
如何利用交换机和端口设置来管理... 在网络管理中,总是有些人让管理员头疼。下面我们就将介绍一下一个网管员利用交换机以及端口设置等来进行D...
什么是大数据安全 什么是大数据... 在《为什么需要大数据安全分析》一文中,我们已经阐述了一个重要观点,即:安全要素信息呈现出大数据的特征...
只需三步,让你掌握阿尔法路由器... 请参照以下阿尔法路由器设置方法,通过浏览器进入及设置宽带路由器。经过这三个步骤的设置,基本上能够熟悉...
全面诠释网络负载均衡 负载均衡的出现大大缓解了服务器的压力,更是有效的利用了资源,提高了效率。那么我们现在来说一下网络负载...
如何允许远程连接到MySQL数... [[277004]]【51CTO.com快译】默认情况下,MySQL服务器仅侦听来自localhos...
如何更省钱? 近期特价热门硒鼓... 如今激光打印设备已经成为商务或企业的绝对主力办公设备,但采购者往往忽视了激光打印设备所用的耗材,相对...