java模拟微信红包,随机红包金额

public class RandomAmountUtil {

    private final BigDecimal big0 = new BigDecimal(0);
    private final BigDecimal big3 = new BigDecimal(3);
    private BigDecimal amount;
    private int count;
    private BigDecimal limit ;
    private int i=0;
    private BigDecimal mean ;

    public RandomAmountUtil(BigDecimal amount,int count,BigDecimal limit){
        this.amount = amount;
        this.count = count;
        this.limit = limit;
        //平均数
        mean = amount.divide(new BigDecimal(count),2,BigDecimal.ROUND_HALF_UP);
    }

    // 求一个平均数,剩余人数ii
    // 最后一位 全给他
    // 以平均数a和剩余金额b计算,
    // b>a 随机+-  +范围0到b-a   -范围0到(a-0.01)
    // b<=a  范围0到(a-(0.01*i))
    public BigDecimal getRandomAmount(){
        i+=1;
        //随机金额 可正可负 用来和平均金额做加法
        BigDecimal random ;
        //计算结果
        BigDecimal returnAmount ;
        //根据人数和最小金额预留,否则后面会出选不够
        BigDecimal reserveAmount ;
        //最后一个 或超出 直接返回
        if(i>=count){
            returnAmount = amount;
        }else{
            //根据人数和最小金额预留,否则后面会出选不够
            reserveAmount = limit.multiply(new BigDecimal(count-i));
            if(amount.compareTo(mean.add(reserveAmount))==1){
                //剩余金额大于 平均金额+预留金额
                //随机正负(随机结果和平均金额做加法)
                if(randomAddType()){
                    //正数 取随机值范围 0-剩余金额减去平均数减去预留金额
                    BigDecimal end = amount.subtract(mean).subtract(reserveAmount);
                    BigDecimal multiple = end.divideAndRemainder(mean)[0];
                    //随机金额范围不能超过平均金额三倍
                    if(multiple.compareTo(big3)==1){
                        end = mean.multiply(big3);
                    }
                    random = getRandomDouble(big0,end,true,limit, true);
                }else{
                    //负数 0-平均金额减去最小金额
                    random = getRandomDouble(big0,mean.subtract(limit),false,limit, true);
                }
                //做加减法
                returnAmount = mean.add(random);
            }else{
                //剩余金额小于平均金额  0-剩余金额-预留金额
                returnAmount = getRandomDouble(big0,amount.subtract(limit.multiply(new BigDecimal(count-i))),true,limit,false);
            }
        }
        amount = amount.subtract(returnAmount);

        return returnAmount;
    }

    private BigDecimal getRandomDouble(BigDecimal begin, BigDecimal end, Boolean isPositive, BigDecimal limit, boolean isZero){
        if(begin.compareTo(end)==0){
            return begin;
        }
        DoubleStream DoubleStream = new Random().doubles(begin.doubleValue(),end.doubleValue());
        BigDecimal randomDouble = new BigDecimal((isPositive?+1:-1)*DoubleStream.iterator().nextDouble()).setScale(2,BigDecimal.ROUND_HALF_UP);
        randomDouble = randomDouble.divideAndRemainder(limit)[0].multiply(limit);
        if(!isZero&&randomDouble.compareTo(big0)<=0){
            return limit;
        }
        return randomDouble;
    }
    public static void main(String[] args) {
//        BigDecimal big100 = new BigDecimal("0.02");
//        BigDecimal randomDouble = new BigDecimal("102.01");
//        randomDouble = randomDouble.divideAndRemainder(big100)[0].multiply(big100);
//        System.out.println(randomDouble);

        int count = 100;
        BigDecimal sum = new BigDecimal(0);
        RandomAmountUtil randomAmountUtil = new RandomAmountUtil(new BigDecimal("100"),count, new BigDecimal("0.01"));
        for (int i = 0; i < count; i++) {
            BigDecimal random = randomAmountUtil.getRandomAmount();
            sum=sum.add(random);
            System.out.println(random);
        }
        System.out.println("=="+sum+"==");
    }


    private Boolean randomAddType(){
        int random = new Random().nextInt(4);
        switch (random){
            case 0 : return false;
            case 1 : return true;
            case 2 : return false;
            default:return false;
        }
    };


}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值