红包算法分析
有人认为,抢红包的额度是从0.01到剩余平均值*N(N是一个系数,决定最大的红包值)之间,比如一共发了10块钱,发了10个红包:第一个人可以拿到(0.01~1*N)之间的一个红包值,当然为了确保所有人至少有1分钱拿,不能前几个人就把钱拿光了,因此需要有一个判断算法。举个例子,如果每个人都拿了自己的最大值:
package红包分配;public classtest {public static voidmain(String[] args){float num=10,N=1.9f;int people=10;for(int i=0;i<10;i++)
{
System.out.println("the number"+people+"can get "+num/people*N);
num=num-num/people*N;
people--;
}
System.out.println("there remain"+num);
}
}
运行结果如下:
the number10can get 1.9the number9can get1.71the number8can get1.5176251the number7can get1.3225019the number6can get1.1241267the number5can get0.9217838the number4can get0.71438247the number3can get0.5000677the number2can get0.2750373the number1can get0.027503723there remain-0.01302808
最终剩余的钱数为负数,不符合要求,所以说基数的选取是非常重要的。
设置金额的限额
private static final float MINMONEY = 0.01f;private static final float MAXMONEY = 200f;
红包的最小额度是0.01元,最大额度是200元。
判断金额是否合法
如果金额超过限额,就出错了
private boolean isRight(float money,intcount)
{double avg = money/count;if(avg
}else if(avg>MAXMONEY)
{return false;
}return true;
}
随机产生红包
用随机方法产生一个在最大值和最小值之间的一个红包,并判断该红包是否合法,是否在产生这个红包之后红包金额变成负数。另外,在这次产生红包值较小时,下一次就产生一个大一点的红包。
private float randomRedPacket(float money,float mins,float maxs,intcount)
{if(count==1)
{return (float)(Math.round(money*100))/100;
}if(mins ==maxs)
{return mins;//如果最大值和最小值一样,就返回mins
}float max = maxs>money?money:maxs;float one = ((float)Math.random()*(max-mins)+mins);
one= (float)(Math.round(one*100))/100;float moneyOther = money -one;if(isRight(moneyOther,count-1))
{returnone;
}else{//重新分配
float avg = moneyOther / (count-1);if(avg
{returnrandomRedPacket(money,mins,one,count);
}else if(avg>MAXMONEY)
{returnrandomRedPacket(money,one,maxs,count);
}
}returnone;
}
实现红包分配
为了避免一个红包占用大量的资金,设定非最后一个红包的最大金额,可以设置为平均值的N倍,基于前面的方法就可以实现红包的分配了。
private static final float TIMES = 2.1f;public List splitRedPackets(float money,intcount)
{if(!isRight(money,count))
{return null;
}
List list = new ArrayList();float max = (float)(money*TIMES/count);
max= max>MAXMONEY?MAXMONEY:max;for(int i=0;i
{float one = randomRedPacket(money,MINMONEY,max,count-i);
list.add(one);
money-=one;
}returnlist;
}
private static final float TIMES = 2.1f;public List splitRedPackets(float money,intcount)
{if(!isRight(money,count))
{return null;
}
List list = new ArrayList();float max = (float)(money*TIMES/count);
max= max>MAXMONEY?MAXMONEY:max;for(int i=0;i
{float one = randomRedPacket(money,MINMONEY,max,count-i);
list.add(one);
money-=one;
}returnlist;
}
编写主函数
public static voidmain(String[] args) {
RedPacketUtil util= newRedPacketUtil();
System.out.println(util.splitRedPackets(200, 100));
}