import java.math.BigDecimal; import java.math.RoundingMode; import java.util.Collections; import java.util.List; import com.google.common.collect.Lists; public class RedBagUtils { /** * 每个红包最小金额,单位为分 */ private static final int MIN_MONEY = 1; /** * 红包金额的离散程度,值越大红包金额越分散 */ private static final double DISPERSE = 10; /** * 根据剩余的红包金额和红包个数,获取一个红包的金额 * @param amount 剩余金额,单位为元 * @param count 剩余红包数 * @return 红包金额, 单位为元 */ public static BigDecimal getOneRedBag(BigDecimal amount, int count) { //将 元*100 转为分 int money = amount.setScale(2, RoundingMode.HALF_UP).multiply(new BigDecimal(100)).intValue(); if (money / count < MIN_MONEY) { throw new RuntimeException("最小值设置过大"); } //最大值 = 均值*离散程度 int max = (int) (money * DISPERSE / count); //最大值不能大于总金额 max = max > money ? money : max; return new BigDecimal(randomBetweenMinAndMax(money, count, MIN_MONEY, max)).divide(new BigDecimal(100), 2, RoundingMode.HALF_UP); } /** * 在最小值和最大值之间随机产生一个红包 * @param money * @param count * @param min : 最小金额 * @param max : 最大金额 * @return */ private static int randomBetweenMinAndMax(int money, int count, int min, int max) { //最后一个红包直接返回 if (count == 1) { return money; } //最小和最大金额一样,返最小和最大值都行 if (min == max) { return min; } //最小值 == 均值, 直接返回最小值 if (min == money / count) { return min; } //min<=随机数bag<=max int bag = ((int) Math.rint(Math.random() * (max - min) + min)); //剩余的均值 int avg = (money - bag) / (count - 1); //比较验证剩余的红包还够不够分(均值>=最小值 是必须条件),不够分的话就是最大值过大 if (avg < MIN_MONEY) { /* * 重新随机一个红包,最大值改成本次生成的红包金额 * 由于 min<=本次红包金额bag<=max, 所以递归时bag是不断减小的。 * bag在减小到min之间一定有一个值是合适的,递归结束。 * bag减小到和min相等时,递归也会结束,所以这里不会死递归。 */ return randomBetweenMinAndMax(money, count, min, bag); } else { return bag; } } public static void main(String[] args) { //红包金额 BigDecimal amount = new BigDecimal(100); //红包个数 int count = 50; //累计单个红包的金额,最后这个数要和amount一致才对 BigDecimal total = new BigDecimal(0); List<BigDecimal> list = Lists.newArrayList(); for (int i = 0; i < count; i++) { BigDecimal tem = getOneRedBag(amount.subtract(total), count - i); total = total.add(tem); list.add(tem); System.out.println("第" + (count - i) + "个红包的金额是:" + total + "元"); } //总金额是否相等 System.out.println("总计金额是否相等:" + (total.compareTo(amount) == 0)); System.out.println("红包个数:" + list.size()); System.out.println("红包金额明细:" + list); Collections.sort(list); System.out.println("排序后的红包明细:" + list); } }
java 仿微信红包生成
传入金额和红包个数即可,直接上代码
猜你喜欢
转载自18810098265.iteye.com/blog/2369857
今日推荐
周排行