红包算法 java实现

红包算法

首先,如果红包只有一个,本轮直接使用全部金额,确保红包发完。

然后,
计算出本次红包最少要领取多少,才能保证红包领完,即本轮下水位;
本轮最多领取多少,才能保证每个人都领到,即本轮上水位。

主要方式如下:
计算本次红包金额下水位:假设本次领到最小值1分,那接下来每次都领到200元红包能领完,那下水位为1分;如果不能领完,那按接下来每次都领200元,剩下的本轮应全部领走,是本轮的下水位。

计算本轮红包上水位:假设本轮领200元,剩下的钱还足够接下来每轮领1分钱,那本轮上水位为200元;如果已经不够领,那按接下来其他领1分,计算本轮的上水位。

为了使红包金额不要太悬殊,使用红包均值调整上水位。如果上水位金额大于两倍红包均值,那么使用两倍红包均值作为上水位。换句话说,每一轮抢到的红包金额,最高为两倍剩下红包的均值。

最后,获取随机数并用上水位取余,如果结果比下水位还小,则直接使用下水位,否则使用随机金额为本轮拆到金额。

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.Random;

public class RandomRedPocket implements RedPocket {

    BigDecimal avgAmount;

    private BigDecimal totalAmount;

    private BigDecimal lowestAmount;


    private Integer remainNum;


    public RandomRedPocket(BigDecimal totalAmount, int num) {
        this.totalAmount = totalAmount;
        this.remainNum = num;
        this.avgAmount = totalAmount.divide(new BigDecimal(num), 2, RoundingMode.HALF_UP).multiply(BigDecimal.valueOf(2));
        this.lowestAmount = BigDecimal.valueOf(0.01);
    }


    @Override
    public BigDecimal getAmount() {
        if (remainNum == 1) {
            return totalAmount;
        } else {
            BigDecimal lowerBound = calculateLowerBound();
            BigDecimal upperBound = calculateUpperBound();
            if (upperBound.compareTo(avgAmount) > 0) {
                upperBound = avgAmount;
            }
            remainNum = remainNum - 1;
            BigDecimal randomAmount = genRandomMoney(lowerBound, upperBound);
            totalAmount = totalAmount.subtract(randomAmount);
            return randomAmount;
        }
    }

    private BigDecimal calculateUpperBound() {
        //后面每人获取最低红包,需要剩下多少钱
        BigDecimal multiplied = lowestAmount.multiply(BigDecimal.valueOf(remainNum - 1));
        BigDecimal upperBound = totalAmount.subtract(multiplied);

        return upperBound;
    }

    //计算本次红包,最低领取多少金额,才能保证红包领完
    //此处可进一步完善
    private BigDecimal calculateLowerBound() {
	

        return BigDecimal.valueOf(0.01);
    }


    @Override
    public boolean isValid(BigDecimal totalAmount, BigDecimal thisAmount) {
        return false;
    }

    @Override
    public BigDecimal genRandomMoney(BigDecimal lowerBound, BigDecimal upperBound) {
        Random random = new Random();
        double randomItem = random.nextDouble();
        BigDecimal decimal = upperBound.subtract(lowerBound).multiply(new BigDecimal(randomItem)).add(lowerBound);
        decimal = decimal.setScale(2, RoundingMode.HALF_UP);
        return decimal;
    }
}

你可能感兴趣的:(java)