• 红包算法 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;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
  • 相关阅读:
    Java教程:学会写Starter-你就懂了SpringBoot自动配置
    酒店品牌纷纷冲击中高端,东呈集团能否“快人一步”?
    nginx降权+安装php
    SpringBoot配置文件的加载顺序
    CIA DS402 DEFINITIONS AND ABBREVIATION
    无法将RELEASE.pom上传到nexus的解决办法
    vue3 blob下载流文件
    【发表案例】网络智能类SCI&EI,仅25天录用,录用后15天见刊,见刊后16天检索
    ESP8266-Arduino编程实例-土壤湿度传感器驱动
    关于操作系统安全补丁信息的查询
  • 原文地址:https://blog.csdn.net/qq_44073614/article/details/134308202