java 随机红包算法

【java 随机红包算法】随机红包算法,每个人都有自己的实现思路 。

package com.jmmq.load.jim.algorithm; import java.math.BigDecimal; import java.util.Arrays; import java.util.List; import java.util.Random; /** * 红包算法 */ public class RedPacketPrc { private static final BigDecimal MIN = new BigDecimal("0.01"); public static void main(String[] args) { String[] rs = redPacketRandom(new BigDecimal(1), 100, false); BigDecimal sum = BigDecimal.ZERO; for(String str: rs){ System.out.println(str); sum = sum.add(new BigDecimal(str)); } System.out.println("sum:" + sum); System.out.println("(ˉ`?._.? ?._.?′ˉ)(ˉ`???′ˉ) (ˉ`?._.? ?._.?′ˉ)(ˉ`???′ˉ) (ˉ`?._.? ?._.?′ˉ)(ˉ`???′ˉ)"); String[] res = redPacketOpen(new BigDecimal(20), 6, false); BigDecimal sum2 = BigDecimal.ZERO; for(String str: res){ System.out.println(str); sum2 = sum2.add(new BigDecimal(str)); } System.out.println("sum2:" + sum2); } /** * * @param faceValue 面值 单位:元 * @param amount人数 * @param avgFlag 是否平均 * @return *平均分就不写了 *思路一: *按百分比进行随机计算,最后一个进行匝差计算 */ public static String[] redPacketRandom(BigDecimal faceValue, int amount, boolean avgFlag){ // 先计算平均数四舍五入 BigDecimal perValue = http://www.jtqzxx.com/smbk/faceValue.divide(new BigDecimal(amount),3, BigDecimal.ROUND_HALF_UP); // 平均下来最小的红包必须大于等于 1分钱 if(perValue.compareTo(MIN) == -1){ throw new RuntimeException("red packet amount OutOfBoundsmin = 0.01"); } String[] rs = new String[amount]; // 平均 if(avgFlag){ // 这里四舍五入重新计算 perValue = faceValue.divide(new BigDecimal(amount),2, BigDecimal.ROUND_HALF_UP); Arrays.fill(rs, perValue.toString()); // 无法除尽 if(perValue.multiply(new BigDecimal(amount)).compareTo(faceValue) != 0 ){ // 随机获取一个下标 int index = new Random().nextInt(amount); rs[index] = String.valueOf(new BigDecimal(rs[index]).add( faceValue.subtract(perValue.multiply(new BigDecimal(amount))))); } return rs; } BigDecimal weightSum = BigDecimal.ZERO; BigDecimal redSum = BigDecimal.ZERO; BigDecimal[] weights = new BigDecimal[amount]; // 随机 for (int i=0; i -1 ){ rs[i] = new BigDecimal(rs[i]).add(diff).toString(); break; } } } // 若没有任何一个元素能吃掉差额,因此差额需要进行分摊了, // 这里简单粗暴的将循环到大于MIN的都改为MIN同时减少差额 // 这里代码不进行优化,会写另外一个优化的算法 if(faceValue.compareTo(redSum) != 0){ for(int i=0; i 0){ if(new BigDecimal(rs[i]).add(diff).compareTo(MIN) > -1){ rs[i] = new BigDecimal(rs[i]).add(diff).toString(); break; } else { diff.add(new BigDecimal(rs[i])).subtract(MIN); rs[i] = MIN.toString(); } } } } return rs; } /** *上面算法进行优化 * @param faceValue 面值 单位:元 * @param amount人数 * @param avgFlag 是否平均 * @return *优化思路: *上面算法为了保证红包最小金额处理上花费了大量的循环来处理 *优化上就直接先分配最小金额,然后在进行随机分摊剩余的钱 */ public static String[] redPacketOpen(BigDecimal faceValue, int amount, boolean avgFlag){ // 先计算平均数四舍五入 BigDecimal perValue = faceValue.divide(new BigDecimal(amount),3, BigDecimal.ROUND_HALF_UP); // 平均下来最小的红包必须大于等于 1分钱 if(perValue.compareTo(MIN) == -1){ throw new RuntimeException("red packet amount OutOfBoundsmin = 0.01"); } String[] rs = new String[amount]; // 平均 if(avgFlag){ // 这里四舍五入重新计算 perValue = faceValue.divide(new BigDecimal(amount),2, BigDecimal.ROUND_HALF_UP); Arrays.fill(rs, perValue.toString()); // 无法除尽 if(perValue.multiply(new BigDecimal(amount)).compareTo(faceValue) != 0 ){ // 随机获取一个下标 int index = new Random().nextInt(amount); rs[index] = String.valueOf(new BigDecimal(rs[index]).add( faceValue.subtract(perValue.multiply(new BigDecimal(amount))))); } return rs; } // 随机 // 先把低保放进去 Arrays.fill(rs, MIN.toString()); BigDecimal weightSum = BigDecimal.ZERO; BigDecimal redSum = BigDecimal.ZERO; BigDecimal[] weights = new BigDecimal[amount]; // 随机 for (int i=0; i

    推荐阅读