带有上下限的红包(java)

本文介绍了一种在限定条件下的红包分配算法实现,确保了在特定的上下限范围内随机生成的红包金额既符合平均值规律又能体现随机性。适用于红包数量超过100时采用上下限随机算法,数量少于100时则采用平均值倍增算法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

昨天同事说写的红包算法,无法保证在具有上下限和固定数量、固定金额的条件下完美执行(红包数量为零之后红包金额为零)

今天试着写了一下,本人通过简单的测试,分享一下,有不足的地方还希望指正。

注:1、因为采用的是小数,为了达到精度准确,计算采用Bigdecimal。

       2、满足条件:最小值*红包数量<总金额<最大值*红包数量。

说明:该程序并非完全是让金额采用具有上下限的算法,而是和平均值*2的算法结合使用,

        红包数量大于100采用具有上下限的算法,为了体现随机性,即 不能让大于数量100的全部采用具有上下限的算法而导致数量小于100的时候,随机数的风格差距过大,所以有了 randomNumConf()方法(代码中注释有说明)

        为了保证红包金额为零且数量为零,当红包数量小于100则完全采用平均值*2的方式计算红包随机数。

代码:

    /**
     *
     * @param randomMax 随机数期间最大值
     * @param randomMin 随机数期间最小值
     * @return double
     */
    public static double randomNum(double randomMax,double randomMin){
        Random random = new Random();
        double randomMoney = Math.floor(random.nextDouble()*100*randomMax)/100;
        BigDecimal randomMoneyBigDeximal = BigDecimal.valueOf(randomMoney);
        return randomMoneyBigDeximal.compareTo(BigDecimal.valueOf(randomMin))>0?randomMoney:randomMin;
    }

    /**
     * 按照平均数*2的随机算法生成红包
     * @param vagXTwo
     * @return
     */
    public static double randomByVagXTwo(double vagXTwo,double rdMin){
        double rdMoney = Math.floor(new Random().nextDouble()*100*vagXTwo)/100;
        return BigDecimal.valueOf(rdMoney).compareTo(BigDecimal.valueOf(rdMin))>0?rdMoney:rdMin;
    }
    /**
     *如果 rdNum>subMax 按照限制上下限来随机生成红包,否则按照平均数*2的随机算法生成红包 (1-subMax) 为有上下限的概率
     * @return
     */
    public static boolean randomNumConf(){
        double subMax = 0.5;
        double rdNum = Math.floor(Math.random()*100)/100;
        return BigDecimal.valueOf(rdNum).compareTo(BigDecimal.valueOf(subMax))>0?true:false;
    }
    /**
     * @param totalBonus 总金额
     * @param totalNum 总数
     * @param randomMax 随机最大
     * @param randomMin 随机最小
     * @return double
     */
    public static double bonus(double totalBonus,int totalNum,double randomMax,double randomMin){
        double bonusVAG = BigDecimal.valueOf(totalBonus).divide(BigDecimal.valueOf(totalNum),2,BigDecimal.ROUND_DOWN).doubleValue(); // 剩余金额平均值
        double rdMoney;
        // 最大值大于总金额
        boolean isDo = BigDecimal.valueOf(randomMax).compareTo(BigDecimal.valueOf(totalBonus))>0;
        if(isDo){randomMax = totalBonus;}
        if(randomNumConf() && totalNum>100 && !isDo){
            rdMoney = randomNum(randomMax,randomMin);
        }else{
            randomMin=0.01;
            if (totalNum == 1) {
                return (double) Math.round(totalBonus * 100) / 100;
            }
            rdMoney = randomByVagXTwo(BigDecimal.valueOf(bonusVAG).multiply(BigDecimal.valueOf(2)).doubleValue(),randomMin);
        }
        totalBonus=BigDecimal.valueOf(totalBonus).subtract(BigDecimal.valueOf(rdMoney)).doubleValue();
        return rdMoney;
    }
    public static void test(double totalBonus,int totalNum,double randomMax,double randomMin){
        BigDecimal b = BigDecimal.ZERO;
        int c = totalNum;
        for (int i = 0; i <c; i++) {
            double n = bonus(totalBonus,totalNum,randomMax,randomMin);
            totalBonus = BigDecimal.valueOf(totalBonus).subtract(BigDecimal.valueOf(n)).doubleValue();
            totalNum--;
            b=b.add(BigDecimal.valueOf(n));
            System.out.print(n+"   ");
        }
        System.out.println();
        System.out.println("红包总数:"+b);
    }

    public static void main(String[] args){
        for (int i = 0; i <100 ; i++) {
            test(2000,1000,10,0.5);
        }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值