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
