import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Random; import javax.swing.JOptionPane; /** * 金额随机分配算法 * @author kwf * @since 2018-2-9 11:03:59 */ public class Main { //需要设置的参数 private static final double MIN_MONEY = 0.1; //用户获得的最小金额 private static final double MAX_MONEY = 10; //用户获得的最大金额(可能存在误差。主要用于计算倍数,值为0则使用默认倍数) private static final double TOTAL_MONEY = 100;//总金额 private static final int TOTAL_COUNT = 50;//总份数 private static final boolean IS_UPSET = true;//结果是否需要打乱 private static double times = 2;//倍数(用户获得的最大金额=当前平均值*倍数,当前平均值=剩余金额/剩余份数)(若最大金额不为0则会被重新赋值) private static double leftMoney = TOTAL_MONEY; //剩余金额 private static int leftCount = TOTAL_COUNT;//剩余份数 private static int runCount = 0;//运行次数 private static int minCount = 0;//算法中获得的最小金额的个数 private static double maxValue, minValue; //算法中获得的最大值和最小值 public static void main(String[] args) { System.out.println("倍数为" + setTimes()); if(!isRight(TOTAL_MONEY, TOTAL_COUNT)) { //如果设置金额和份数不合法则报错 JOptionPane.showMessageDialog(null, "平均值为小于最小金额", "出错啦", JOptionPane.ERROR_MESSAGE); return; } List<Double> list = new ArrayList<>(); //用于存储金额列表 double total = 0;//用于存储金额列表的总值 int size = TOTAL_COUNT; for(int i = 0; i < size; size--) { double money = getRandomMoney(); list.add(money); total += money; if(Double.doubleToLongBits(money) == Double.doubleToLongBits(MIN_MONEY)) minCount ++; } if(IS_UPSET) { System.out.println("打乱前:" + list); //打印打乱前的金额列表 Collections.shuffle(list);//打乱列表 System.out.println("打乱后:" + list); //打印打乱后的金额列表 } else{ System.out.println(list); //打印金额列表 } System.out.println("数组总额为" + Math.round(total) + "=>" + (Math.round(total) == Math.round(TOTAL_MONEY) ? "合法" : "不合法")); System.out.println("随机算法运行了" + runCount + "次"); //打印金额列表 maxValue = minValue = list.get(0); for(double value:list) { maxValue = value > maxValue ? value : maxValue; minValue = value < minValue ? value : minValue; } System.out.println("最大值为" + maxValue + ",最小值为" + minValue); System.out.println("最小金额的个数为" + minCount); } /** * 随机算法 * @return 随机金额 */ public static double getRandomMoney() { runCount ++; if (leftCount == 1) { return (double) Math.round(leftMoney * 100) /100; } Random r = new Random(); double max = leftMoney / leftCount * times; double money = r.nextDouble() * max; money = money <= MIN_MONEY ? MIN_MONEY : money; money = Math.floor(money * 100) / 100; if(isRight(leftMoney - money, leftCount - 1)) { leftMoney -= money; leftCount--; return money; } else {//如果不合法则递归调用随机算法,直到合法 return getRandomMoney(); } } /** * 判断金额和份数是否合法,平均值小于最小金额则视为不合法 * @param money 金额 * @param count 份数 * @return 合法性 */ private static boolean isRight(double money, int count) { return money / count >= MIN_MONEY; } /** * 设置倍数(仅当设置了最大金额才有效,否则为默认倍数) * @return 倍数 */ private static double setTimes() { if(MAX_MONEY != 0) { times = MAX_MONEY / (TOTAL_MONEY / TOTAL_COUNT); } return times; } }
10次运行结果如下
第1次运行结果 倍数为2.5 打乱前:[1.54, 4.59, 3.19, 1.8, 2.67, 0.66, 0.1, 2.07, 4.05, 3.59, 4.31, 4.03, 3.27, 1.06, 0.28, 2.13, 1.08, 4.46, 2.4, 2.5, 3.39, 3.49, 0.23, 3.34, 1.06, 1.97, 3.49, 3.15, 3.26, 1.87, 2.71, 2.82, 0.99, 1.35, 0.83, 0.97, 1.68, 0.8, 1.61, 1.56, 2.05, 0.33, 0.38, 1.54, 1.71, 1.3, 0.32, 0.91, 0.8, 0.31] 打乱后:[1.97, 0.97, 0.23, 3.39, 0.83, 3.49, 3.49, 3.19, 0.91, 4.46, 0.31, 1.8, 1.68, 1.71, 1.3, 2.82, 4.59, 0.33, 1.35, 3.34, 0.66, 1.61, 2.05, 4.05, 1.54, 2.07, 1.06, 0.32, 3.59, 3.27, 4.31, 3.26, 1.56, 1.87, 2.71, 0.38, 0.99, 0.8, 2.13, 2.4, 1.08, 4.03, 0.8, 3.15, 2.5, 1.54, 2.67, 0.1, 1.06, 0.28] 数组总额为100=>合法 随机算法运行了50次 最大值为4.59,最小值为0.1 最小金额的个数为1 第2次运行结果 倍数为2.5 打乱前:[3.67, 3.61, 2.48, 1.64, 1.4, 0.1, 4.03, 0.46, 2.25, 2.9, 4.03, 4.59, 2.27, 0.69, 2.14, 2.0, 4.33, 2.28, 0.3, 1.03, 2.14, 0.86, 1.29, 2.5, 0.84, 1.26, 0.71, 3.84, 3.47, 3.17, 2.94, 0.79, 0.54, 4.03, 0.16, 2.97, 3.36, 0.63, 1.49, 3.0, 1.07, 1.4, 0.75, 0.85, 2.35, 0.43, 0.1, 4.33, 1.59, 0.94] 打乱后:[1.4, 4.03, 4.33, 0.85, 2.27, 2.97, 2.0, 1.03, 0.86, 0.16, 0.69, 2.48, 3.61, 4.03, 2.5, 2.14, 1.29, 3.0, 3.67, 4.33, 0.1, 0.71, 0.75, 3.36, 0.94, 0.1, 0.79, 0.63, 1.49, 0.84, 2.35, 0.46, 3.17, 3.47, 4.03, 2.14, 2.25, 1.64, 2.94, 1.59, 4.59, 0.43, 2.9, 0.3, 3.84, 1.07, 1.26, 0.54, 2.28, 1.4] 数组总额为100=>合法 随机算法运行了50次 最大值为4.59,最小值为0.1 最小金额的个数为2 第3次运行结果 倍数为2.5 打乱前:[0.85, 4.47, 0.52, 1.31, 0.39, 4.98, 4.01, 2.14, 1.21, 4.37, 0.51, 4.14, 1.53, 4.14, 0.28, 0.22, 3.46, 0.26, 3.75, 0.39, 4.67, 0.88, 4.26, 4.0, 1.83, 2.47, 2.95, 2.48, 3.5, 2.73, 1.42, 1.94, 1.43, 2.28, 0.8, 1.09, 1.04, 0.41, 3.1, 0.82, 0.1, 1.0, 3.34, 0.89, 2.77, 1.67, 1.12, 1.47, 0.31, 0.3] 打乱后:[1.67, 0.52, 0.89, 3.34, 2.28, 0.85, 2.14, 1.42, 3.1, 1.04, 0.82, 0.51, 4.0, 2.47, 0.39, 2.95, 1.47, 4.37, 1.09, 2.73, 0.31, 4.26, 0.22, 0.8, 3.5, 0.39, 1.43, 4.14, 4.14, 3.46, 1.0, 1.12, 2.77, 4.47, 0.26, 4.67, 1.83, 0.88, 1.94, 1.53, 4.98, 0.41, 1.31, 3.75, 0.1, 4.01, 2.48, 1.21, 0.28, 0.3] 数组总额为100=>合法 随机算法运行了50次 最大值为4.98,最小值为0.1 最小金额的个数为1 第4次运行结果 倍数为2.5 打乱前:[1.37, 3.39, 0.87, 2.99, 3.41, 1.45, 3.86, 2.3, 0.27, 1.5, 1.58, 0.67, 2.38, 3.88, 0.14, 0.28, 1.91, 2.85, 0.25, 0.93, 3.38, 2.72, 2.8, 1.99, 5.0, 3.7, 3.25, 2.64, 1.69, 2.94, 0.54, 0.98, 0.71, 0.85, 3.71, 0.21, 3.78, 0.9, 0.1, 4.67, 0.57, 1.14, 3.87, 1.63, 0.99, 2.01, 1.36, 3.59, 0.39, 1.61] 打乱后:[2.64, 1.69, 1.37, 2.72, 1.91, 0.98, 0.71, 0.28, 0.87, 3.88, 1.63, 2.8, 3.38, 1.36, 0.54, 2.38, 0.25, 0.57, 4.67, 0.27, 2.01, 2.3, 2.94, 3.59, 2.99, 3.78, 3.87, 5.0, 0.14, 0.67, 0.9, 3.86, 0.93, 3.39, 3.41, 0.99, 0.21, 1.99, 2.85, 0.1, 1.61, 1.45, 0.85, 1.5, 3.71, 1.58, 0.39, 1.14, 3.7, 3.25] 数组总额为100=>合法 随机算法运行了50次 最大值为5.0,最小值为0.1 最小金额的个数为1 第5次运行结果 倍数为2.5 打乱前:[3.35, 3.28, 3.99, 1.31, 0.68, 4.56, 4.28, 1.03, 3.09, 1.37, 0.88, 3.65, 3.11, 2.11, 1.23, 0.99, 4.05, 3.44, 2.11, 3.77, 2.37, 0.74, 0.82, 1.71, 0.4, 3.38, 1.8, 3.4, 0.1, 0.86, 1.15, 1.77, 0.35, 1.85, 3.53, 3.29, 3.1, 2.69, 1.94, 2.16, 0.57, 1.29, 0.8, 1.56, 1.45, 1.61, 1.77, 0.98, 0.1, 0.18] 打乱后:[4.28, 1.37, 1.77, 2.16, 1.45, 2.11, 0.74, 1.56, 1.85, 3.44, 1.29, 0.88, 1.15, 3.65, 1.31, 0.82, 3.38, 1.71, 3.11, 1.23, 0.68, 1.77, 2.37, 0.86, 0.18, 0.1, 1.61, 3.09, 0.98, 3.77, 3.4, 1.94, 3.99, 1.03, 0.99, 0.8, 0.1, 3.53, 2.69, 2.11, 0.35, 3.35, 3.1, 3.29, 0.57, 4.05, 0.4, 4.56, 1.8, 3.28] 数组总额为100=>合法 随机算法运行了50次 最大值为4.56,最小值为0.1 最小金额的个数为2 第6次运行结果 倍数为2.5 打乱前:[2.1, 4.6, 3.04, 3.49, 0.1, 1.77, 3.29, 2.83, 4.3, 2.76, 3.86, 2.22, 1.83, 2.33, 1.87, 2.04, 3.81, 1.57, 2.01, 0.1, 3.76, 0.68, 0.66, 1.94, 0.12, 3.32, 1.05, 0.1, 1.01, 2.36, 1.46, 4.05, 0.93, 1.14, 4.02, 1.74, 1.77, 2.12, 2.6, 0.1, 0.81, 2.46, 1.62, 0.1, 0.44, 0.11, 1.1, 3.72, 2.21, 2.58] 打乱后:[0.12, 3.86, 1.62, 4.05, 3.32, 0.93, 1.74, 0.1, 3.04, 1.57, 2.12, 1.01, 2.83, 2.46, 0.66, 4.6, 3.29, 4.3, 2.22, 1.05, 2.21, 2.1, 1.77, 1.94, 2.01, 0.81, 3.76, 1.77, 0.1, 4.02, 0.1, 2.36, 2.04, 2.6, 1.46, 1.87, 2.33, 0.1, 3.49, 2.58, 3.72, 2.76, 0.44, 0.1, 3.81, 1.1, 0.68, 1.14, 1.83, 0.11] 数组总额为100=>合法 随机算法运行了50次 最大值为4.6,最小值为0.1 最小金额的个数为5 第7次运行结果 倍数为2.5 打乱前:[2.45, 4.0, 0.15, 2.04, 4.42, 4.79, 0.45, 2.97, 4.6, 1.09, 0.31, 4.31, 0.54, 1.95, 4.37, 2.18, 3.59, 2.2, 3.28, 2.35, 3.0, 1.78, 2.0, 0.29, 2.41, 1.34, 3.69, 0.25, 3.68, 2.5, 2.17, 3.15, 2.94, 1.71, 1.67, 1.23, 1.91, 0.63, 0.77, 2.43, 2.06, 1.36, 1.12, 0.83, 0.14, 1.4, 0.25, 0.37, 0.69, 0.19] 打乱后:[2.2, 0.29, 3.15, 1.91, 0.63, 4.42, 4.31, 0.69, 2.41, 3.0, 2.35, 1.23, 1.4, 0.37, 2.17, 0.25, 2.0, 2.5, 4.6, 2.06, 1.67, 1.95, 0.77, 1.09, 1.78, 3.69, 3.59, 3.68, 4.79, 0.19, 0.31, 0.15, 2.04, 1.12, 1.34, 4.37, 0.54, 2.43, 2.97, 4.0, 3.28, 1.71, 2.45, 0.45, 0.83, 0.14, 2.18, 1.36, 2.94, 0.25] 数组总额为100=>合法 随机算法运行了51次 最大值为4.79,最小值为0.14 最小金额的个数为0 第8次运行结果 倍数为2.5 打乱前:[2.52, 2.46, 3.39, 3.8, 1.32, 1.15, 0.26, 2.77, 3.88, 0.73, 4.16, 3.47, 4.14, 4.32, 2.98, 3.61, 1.81, 0.37, 0.67, 3.96, 1.42, 2.84, 1.02, 1.59, 2.64, 3.31, 1.68, 2.18, 1.28, 0.68, 3.1, 1.35, 0.8, 1.72, 1.01, 0.27, 2.61, 1.69, 1.0, 2.79, 0.58, 0.18, 0.92, 0.45, 0.26, 0.81, 0.16, 0.32, 6.73, 2.84] 打乱后:[1.28, 2.84, 0.92, 0.16, 0.37, 0.45, 3.1, 4.32, 2.84, 6.73, 0.58, 2.77, 0.8, 2.61, 4.14, 0.27, 1.0, 0.18, 1.69, 2.98, 3.39, 1.01, 3.47, 0.32, 1.42, 3.88, 1.72, 3.31, 0.67, 2.52, 4.16, 2.18, 2.64, 1.59, 3.61, 0.26, 0.68, 0.73, 1.02, 1.32, 1.35, 3.96, 1.15, 0.26, 2.46, 0.81, 1.68, 2.79, 3.8, 1.81] 数组总额为100=>合法 随机算法运行了51次 最大值为6.73,最小值为0.16 最小金额的个数为0 第9次运行结果 倍数为2.5 打乱前:[0.62, 4.47, 0.95, 3.23, 1.56, 3.99, 2.17, 4.82, 4.07, 1.69, 1.66, 1.24, 2.56, 2.63, 3.87, 1.93, 0.11, 3.33, 2.35, 2.47, 2.68, 3.61, 2.19, 3.59, 1.27, 0.18, 1.81, 0.82, 2.94, 2.95, 0.77, 2.35, 2.59, 1.41, 1.01, 2.0, 2.51, 0.29, 0.24, 2.69, 1.95, 1.98, 1.12, 0.68, 0.75, 1.72, 1.11, 1.06, 1.82, 0.19] 打乱后:[1.69, 2.69, 3.33, 1.24, 1.66, 1.95, 1.98, 0.95, 1.12, 2.35, 4.82, 3.87, 1.72, 1.27, 3.99, 3.23, 3.59, 4.07, 2.95, 2.17, 0.24, 4.47, 0.75, 3.61, 1.56, 1.11, 0.18, 1.93, 2.56, 1.82, 0.77, 1.81, 0.19, 2.47, 0.29, 1.01, 2.19, 0.68, 2.94, 1.06, 0.11, 2.59, 1.41, 2.68, 0.82, 0.62, 2.63, 2.0, 2.35, 2.51] 数组总额为100=>合法 随机算法运行了50次 最大值为4.82,最小值为0.11 最小金额的个数为0 第10次运行结果 倍数为2.5 打乱前:[3.07, 4.15, 4.28, 2.07, 1.97, 2.1, 0.47, 4.07, 1.13, 0.1, 0.89, 3.54, 3.35, 4.09, 0.92, 0.93, 2.03, 3.87, 0.1, 2.7, 0.1, 0.4, 2.14, 0.76, 3.33, 4.07, 2.64, 1.41, 0.13, 2.01, 3.26, 2.95, 0.88, 2.7, 0.72, 2.18, 0.88, 4.52, 3.09, 0.1, 2.63, 3.05, 3.13, 2.25, 0.78, 0.29, 1.67, 1.48, 0.13, 0.49] 打乱后:[0.1, 2.7, 0.49, 3.09, 2.18, 2.1, 0.29, 2.95, 3.87, 4.09, 0.78, 0.13, 3.54, 3.07, 0.4, 2.25, 3.05, 4.07, 0.47, 4.52, 0.13, 0.1, 1.67, 1.13, 0.76, 2.01, 2.03, 3.26, 4.07, 1.48, 0.1, 0.88, 0.89, 0.88, 1.97, 2.64, 3.33, 3.13, 0.72, 1.41, 0.93, 4.15, 0.1, 2.07, 2.63, 4.28, 3.35, 2.14, 2.7, 0.92] 数组总额为100=>合法 随机算法运行了50次 最大值为4.52,最小值为0.1 最小金额的个数为4