java实现微信红包分配算法

红包算法分析

有人认为,抢红包的额度是从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;
}

编写主函数

 public static void main(String[] args) {  
        RedPacketUtil util = new RedPacketUtil();  
        System.out.println(util.splitRedPackets(200, 100));  
    }  
}
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值