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;
}
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));   
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM