红包的随机分配算法

网站换成了HTTPS访问,比以前有逼格了。顺应潮流的使用了Let's encrypt。

最近偶然间想到了红包的分配问题,在这里记录下思路和代码。

问题

发一个N元红包,M人来分,尽量公平每个人拿到的金额。

思路:假设10元红包10个人分,为了保证剩下的人能拿到红包,每个人最大能拿(红包金额-剩余人数*最小金额)的量,但如果每个人都可能拿最大金额,对排在后面的人就不公平,为此需要对取值范围进行调整。

代码一

var RedPacket = function(person,money,min){
	this.person = person; //人数
	this.money = money; //红包金额
	this.min = min; //最小金额
	this.random = 0; //每次抽到的金额

	this.algorithm1 = function(){
		for(let i=1;i<this.person;i++){
			let max = this.money-(this.person-i)*min;
			let avg;
			if(i!=this.person-1){
				do{
					avg = max/(this.person-i)+[max/(this.person-i)]*(1/2); //取值范围公式
				}while(avg>max)
			}else{
				avg = max;
			}
			do{
				this.random = parseFloat(Math.random()*(avg-min)+min); //抽取avg和min之间的随机数
				this.random = Math.floor(this.random*Math.pow(10,2))/Math.pow(10,2); //保留小位数
			}while(this.random>avg||this.random<min)

			this.money = Math.floor((this.money-this.random)*Math.pow(10,2))/Math.pow(10,2);
			console.log("第"+i+"个人拿到了"+this.random+"元钱,还剩"+this.money+"元。");
		}
		console.log("第"+this.person+"个人拿到了最后的"+this.money+"元钱。");
	};
}

测试结果

rp_re1

这个方法每次抽取500次后的结果就如图中所示一样,倒数第二个人之前取得的红包金额量都是递进式的,只有最后两名相对公平。

代码二

var RedPacket = function(person,money,min){
	this.person = person; //人数
	this.money = money; //红包金额
	this.min = min; //最小金额
	this.random = 0; //每次抽到的金额

	this.algorithm2 = function(){
		for(let i=this.person;i>1;i--){
			let max = this.money-(this.person-1)*this.min;
			let avg = i<=2?max:max/i*2; //取值范围公式

			do{
				this.random = parseFloat(Math.random()*(avg-this.min)+this.min); //抽取avg和min之间的随机数
				this.random = Math.floor(this.random*Math.pow(10,2))/Math.pow(10,2);
			}while(this.random>avg||this.random<this.min)

			this.money = Math.floor((this.money-this.random)*Math.pow(10,2))/Math.pow(10,2);
			console.log("第"+(this.person-i+1)+"个人拿到了"+this.random+"元钱,还剩"+this.money+"元。");
		}
		console.log("第"+this.person+"个人拿到了最后的"+this.money+"元钱。");
	};
}

测试结果

rp_re2

第二种方法就相对平稳了很多,极差小了不少,不过我多次抽取几组后,发现最后一个人还是更容易抽的多些,但如果抽上千次来看的话还是很平均的。

测试地址

红包随机算法测试

多次抽取的话,可以在控制台循环调用method(1)或method(0)方法,分别对应第一个和第二个算法。

 Nodejs调用submail邮件接口实现邮件发送
React ES6 + Webpack2搭建项目环境 
上一篇:Nodejs调用submail邮件接口实现邮件发送
下一篇:React ES6 + Webpack2搭建项目环境


已有 6 条评论


  1. 无人小站
    无人小站

    过来膜拜一下dalao

     Reply
    1. MR158
      MR158

      咿呀咿呀咿呀 (°□°;) 还有很多要学的

       Reply
  2. minuo
    minuo

    首先“膜拜”一下,然后想深入的问问,我怎么才能在微信里抢到大红包。哈哈哈。

     Reply
    1. MR158
      MR158

      不知道微信怎么计算的啊,我也想知道哈哈

       Reply
  3. 山野愚人居
    山野愚人居

    微信红包才不公平呢,一个包发出去,分得的差异太大了!

     Reply
  4. 木先森
    木先森

    原来抢红包还有这么多学问,我只知道发红包的一般只抢几分钱,最后(不是倒数第一)抢的人红包一般都很大。

     Reply

如果我的文章对你有帮助,或许可以打赏一下呀!

支付宝
微信
QQ