红包分配算法,总金额分配算法

一个 总数和分配几个点的数据, 但是又不能是平均值,所以写一个随机分配数,每个数的和加在一起等于总金额

类似于红包分配方式,解释说明都写在类里了

解释和说明

* 1  抢红包的期望收益应与先后顺序无关
   2  保证每个用户至少能抢到一个预设的最小金额,人民币红包设置的最小金额一般是0.01元,如果需要发其他货币类型的红包,比如区块链货币或者积分,需要自定义一个最小金额。
   3  所有抢红包的人领取的子红包的金额之和加起来,等于发红包的人发出的总红包的金额。 下面实现的方式是一次生成所有的子红包,让用户按顺序领取。也可以每领取一个生成一个,两种方式性能上各有优劣。

 *  public BigDecimal divide(BigDecimal divisor,int scale, int roundingMode)
    第一个参数是除数,第二个参数代表保留几位小数,第三个代表的是使用的模式。其中我们标题上就是其中的两种
    BigDecimal.ROUND_DOWN:直接省略多余的小数,比如1.28如果保留1位小数,得到的就是1.2

    BigDecimal.ROUND_UP:直接进位,比如1.21如果保留1位小数,得到的就是1.3

    BigDecimal.ROUND_HALF_UP:四舍五入,2.35保留1位,变成2.4

    BigDecimal.ROUND_HALF_DOWN:四舍五入,2.35保留1位,变成2.3

总体红包算法, 1 定义总金额和红包个数 2 确定红包的最大值和最小值
     3 在最大值里随机分配一个小数与之相乘,等到的是实际红包金额
     4 再减去已经生成领取的红包金额和个数。接着下一次再重新计算红包;
     大致如下,
     max = moneytotal/count*2;
    实际红包金额= max*Math.random();
    2.4=4*0.6 红包大小取决于随机大小(0.1~0.9)之间

 

 

 

import java.math.BigDecimal;

/*

* 1 抢红包的期望收益应与先后顺序无关

2 保证每个用户至少能抢到一个预设的最小金额,人民币红包设置的最小金额一般是0.01元,如果需要发其他货币类型的红包,比如区块链货币或者积分,需要自定义一个最小金额。

3 所有抢红包的人领取的子红包的金额之和加起来,等于发红包的人发出的总红包的金额。 下面实现的方式是一次生成所有的子红包,让用户按顺序领取。也可以每领取一个生成一个,两种方式性能上各有优劣。

 

*  public BigDecimal divide(BigDecimal divisor,int scale, int roundingMode)

   第一个参数是除数,第二个参数代表保留几位小数,第三个代表的是使用的模式。其中我们标题上就是其中的两种

   BigDecimal.ROUND_DOWN:直接省略多余的小数,比如1.28如果保留1位小数,得到的就是1.2

 

   BigDecimal.ROUND_UP:直接进位,比如1.21如果保留1位小数,得到的就是1.3

 

  BigDecimal.ROUND_HALF_UP:四舍五入,2.35保留1位,变成2.4

 BigDecimal.ROUND_HALF_DOWN:四舍五入,2.35保留1位,变成2.3

————————————————

总体红包算法, 1 定义总金额和红包个数 2 确定红包的最大值和最小值

3 在最大值里随机分配一个小数与之相乘,等到的是实际红包金额

4 再减去已经生成领取的红包金额和个数。接着下一次再重新计算红包;

大致如下,

max = moneytotal/count*2;

实际红包金额= max*Math.random();

2.4=4*0.6 红包大小取决于随机大小(0.1~0.9)之间

*/

public class RedPackageTask {

public static BigDecimal getRandomMoney(RedPackage _redPackage) {

// remainSize 剩余的红包数量

// remainMoney 剩余的钱

if (_redPackage.remainSize == 1) {

_redPackage.remainSize--;

return _redPackage.remainMoney.setScale(2, BigDecimal.ROUND_DOWN);

}

 

BigDecimal random = BigDecimal.valueOf(Math.random());

BigDecimal min = BigDecimal.valueOf(0.01);

 

BigDecimal halfRemainSize = BigDecimal.valueOf(_redPackage.remainSize).divide(new BigDecimal(2), BigDecimal.ROUND_UP);

BigDecimal max1 = _redPackage.remainMoney.divide(halfRemainSize, BigDecimal.ROUND_DOWN);

BigDecimal minRemainAmount = min.multiply(BigDecimal.valueOf(_redPackage.remainSize - 1)).setScale(2, BigDecimal.ROUND_DOWN);

BigDecimal max2 = _redPackage.remainMoney.subtract(minRemainAmount);

BigDecimal max = (max1.compareTo(max2) < 0) ? max1 : max2;

 

BigDecimal money = random.multiply(max).setScale(2, BigDecimal.ROUND_DOWN);

money = money.compareTo(min) < 0 ? min: money;

_redPackage.remainSize--;

_redPackage.remainMoney = _redPackage.remainMoney.subtract(money).setScale(2, BigDecimal.ROUND_DOWN);;

return money;

}

public static void main(String[] args) {

// 模拟10次抢红包,每次抢到的数据

for (int i = 0; i < 10; i++) {

RedPackage moneyPackage = new RedPackage();

moneyPackage.remainMoney = BigDecimal.valueOf(1000);//总金额

moneyPackage.remainSize = 9;//红包个数

//moneyPackage.remainSize > 0 应该是个数大于0,不然会死循环

while (moneyPackage.remainSize != 0) {

System.out.print(getRandomMoney(moneyPackage) + " ");

}

System.out.println();

}

//每次抢的时候生成红包,实时生成红包,

RedPackage moneyPackage = new RedPackage();

//实时红包就要把remainMoney总金额和remainSize红包个数设置为动态,每抢一个就减掉总金额和红包个数

moneyPackage.remainMoney = BigDecimal.valueOf(1000);//总金额

moneyPackage.remainSize = 10;//红包个数

//moneyPackage.remainSize > 0 应该是个数大于0,不然会死循环

if (moneyPackage.remainSize != 0) {

System.out.print(getRandomMoney(moneyPackage) + " ");

}

System.out.println();

}

}

class RedPackage {

int remainSize;

BigDecimal remainMoney;

}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值