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;
}
};
}