算法还存在如果红包金额数值很小的情况下,有小几率有的用户会分配0的情况,如有建议,还请大神赐教。
注意点 : 红包的金额/可领取人数>=min(最小分配的金额)
public static void main(String[] args) {
Double[] arr = new Double[10];
BigDecimal totalMoney = new BigDecimal("0.2");
int j = 0;
for (int i = 10; i >= 1; i--, j++) {
BigDecimal money = getRandomRedEnvelopeMoney(i, totalMoney);
arr[j] = money.doubleValue();
totalMoney = totalMoney.subtract(money);
}
System.out.println(Arrays.toString(arr));
double sum = 0;
System.out.println(arr.length);
for (int i = 0; i < arr.length; i++) {
sum += arr[i];
}
System.out.println(sum);
}
/**
* 获取随机分配金额
*
* @param remainSize 剩余分配的个数
* @param remainMoney 剩余分配的金额
* @return java.math.BigDecimal
* @throws
* @author liuqiyu
* @date 2019/4/3
* <p>
* 设置红包时,做验证 红包的金额/可领取人数>=min(最小分配的金额)
*/
public static BigDecimal getRandomRedEnvelopeMoney(int remainSize, BigDecimal remainMoney) {
// 随机分配的金额
BigDecimal money;
// 最小分配的金额 (元) BigDecimal 防止科学计算,初始化时使用字符串创建
BigDecimal min = new BigDecimal("0.01");
// 最大分配金额
BigDecimal max;
// 判断红包金额/可领取的人数 与 每个人最小分配金额的对比
int compare = remainMoney.divide(new BigDecimal(remainSize + ""), 2, BigDecimal.ROUND_DOWN).compareTo(min);
// 小于
if (compare < 0) {
throw new RuntimeException("红包的金额/可领取人数小于最小分配金额");
} else if (compare == 0) {
return min;
} else {
if (remainSize == 1) {
// System.out.println("最后一人获取:"+remainMoney);
return remainMoney;
}
if (remainSize < 1) {
return new BigDecimal(0);
}
// 计算可分配最大值
max = remainMoney.subtract(min.multiply(new BigDecimal(remainSize)));
int k = (remainSize) / 2;
if (remainSize <= 2) {
k = remainSize;
}
max = max.divide(new BigDecimal(k), 2, BigDecimal.ROUND_DOWN);
// 计算可分配金额
money = (min.multiply(new BigDecimal(100)).add(new BigDecimal(Math.random()).multiply(max.multiply(new BigDecimal(100)).subtract(min.multiply(new BigDecimal(100)).add(new BigDecimal(1))))));
money = money.divide(new BigDecimal(100), 2, BigDecimal.ROUND_DOWN);
// remainMoney = remainMoney.subtract(money) ;
// System.out.println("第" + remainSize + "个人拿到" + money + "剩下" + remainMoney);
return money;
}
}