红包算法分析

有人认为,抢红包的额度是从0.01到剩余平均值*N(N是一个系数,决定最大的红包值)之间,比如一共发了10块钱,发了10个红包:第一个人可以拿到(0.01~1*N)之间的一个红包值,当然为了确保所有人至少有1分钱拿,不能前几个人就把钱拿光了,因此需要有一个判断算法。举个例子,如果每个人都拿了自己的最大值:

package 红包分配;

public class test {
public static void main(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.9
the number9can get 1.71
the number8can get 1.5176251
the number7can get 1.3225019
the number6can get 1.1241267
the number5can get 0.9217838
the number4can get 0.71438247
the number3can get 0.5000677
the number2can get 0.2750373
the number1can get 0.027503723
there remain-0.01302808

最终剩余的钱数为负数,不符合要求,所以说基数的选取是非常重要的。

设置金额的限额

private static final float MINMONEY = 0.01f;
private static final float MAXMONEY = 200f;

红包的最小额度是0.01元,最大额度是200元。

判断金额是否合法

如果金额超过限额,就出错了

private boolean isRight(float money,int count)
{
double avg = money/count;
if(avg<MINMONEY){
return false;
}
else if(avg>MAXMONEY)
{
return false;
}
return true;
}

随机产生红包

用随机方法产生一个在最大值和最小值之间的一个红包,并判断该红包是否合法,是否在产生这个红包之后红包金额变成负数。另外,在这次产生红包值较小时,下一次就产生一个大一点的红包。

private float randomRedPacket(float money,float mins,float maxs,int count)
{
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))
{
return one;
}
else{
//重新分配
float avg = moneyOther / (count-1);
if(avg<MINMONEY)
{
return randomRedPacket(money,mins,one,count);
}else if(avg>MAXMONEY)
{
return randomRedPacket(money,one,maxs,count);
}
}
return one;
}

实现红包分配

为了避免一个红包占用大量的资金,设定非最后一个红包的最大金额,可以设置为平均值的N倍,基于前面的方法就可以实现红包的分配了。

private static final float TIMES = 2.1f;

public List<Integer> splitRedPackets(float money,int count)
{
if(!isRight(money,count))
{
return null;
}
List<Float> list = new ArrayList<Float>();
float max = (float)(money*TIMES/count); max = max>MAXMONEY?MAXMONEY:max;
for(int i=0;i<count;i++)
{
float one = randomRedPacket(money,MINMONEY,max,count-i);
list.add(one);
money-=one;
}
return list;
}
private static final float TIMES = 2.1f;

public List<Integer> splitRedPackets(float money,int count)
{
if(!isRight(money,count))
{
return null;
}
List<Float> list = new ArrayList<Float>();
float max = (float)(money*TIMES/count); max = max>MAXMONEY?MAXMONEY:max;
for(int i=0;i<count;i++)
{
float one = randomRedPacket(money,MINMONEY,max,count-i);
list.add(one);
money-=one;
}
return list;
}

编写主函数

 public static void main(String[] args) {
RedPacketUtil util = new RedPacketUtil();
System.out.println(util.splitRedPackets(200, 100));
}

最新文章

  1. IDF-CTF-牛刀小试-啥?
  2. HiHo Coder字典树 TrieTree
  3. aa12
  4. JS 获取FileUpload1控件地址
  5. google 火狐 模拟显示手机页面插件
  6. EasyUi &ndash; 6.easyui常见问题
  7. Java程序设计 实验二 Java面向对象程序设计
  8. 数组排序-冒泡排序-选择排序-插入排序-希尔排序-快速排序-Java实现
  9. PHP-Fcgi下PHP的执行时间设置方法
  10. OSGi之Bundle
  11. Haskell 笔记(四)函数系统
  12. php审核操作
  13. NetBeans导入项目jar路径错误解决办法
  14. 转载-Mac下iterm无法使用rz并提示waiting to receive.**B0100000023be50
  15. HDU 4027 Can you answer these queries【线段树】
  16. 【转】20-TCP 协议(滑动窗口——基础)
  17. IOC容器的创建
  18. VS2015 无法启动IIS Express Web服务器(已解决)
  19. python文件备份与简单操作
  20. 控制反转(IOC) 和依赖注入(DI) 的理解

热门文章

  1. 微软Visual Studio二十周年:VS2017于3月7日发布
  2. executssql 函数的每一句代码的意思
  3. css3绘制腾讯logo
  4. Xamarin组件包 Xamarin.ToolKit
  5. angularjs购物车效果
  6. 2017-2-19 C#基础 基本数据类型的转换,转义字符,常量
  7. Omi命令行界面omi-cli发布
  8. .Net小白的第一篇博客
  9. eclipse中注释常用关键字
  10. 禁止Linux系统被 ping