金额随机分配算法

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

 

posted @ 2018-02-08 18:33  请输入...昵称  阅读(3017)  评论(0编辑  收藏  举报