• 金额随机分配算法(修改版)


    import java.util.ArrayList;
    import java.util.Collections;
    import java.util.List;
    import java.util.Random;
    
    /**
     * 金额随机分配算法
     * @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 = 0; //用户获得的最大金额(可能存在误差。主要用于计算倍数,值为0则使用默认倍数)
        private static final double TOTAL_MONEY = 888;//总金额
        private static final int TOTAL_COUNT = 3000;//总份数
        private static final boolean IS_UPSET = true;//结果是否需要打乱
        private static double times = 10;//倍数(用户获得的最大金额=当前平均值*倍数,当前平均值=剩余金额/剩余份数)(若最大金额不为0则会被重新赋值)
        private static double AVG_SCALE = 0.8;//趋于均值的比例
        private static double AVG_FLOAT_SCALE = 0.5;//均值上下浮动的比例
        
        private static double avgMoney = TOTAL_MONEY / TOTAL_COUNT;//平均值
        
        private static int avgCount = (int)Math.floor(TOTAL_COUNT * AVG_SCALE);//趋于均值的份数
        private static double randomCount = TOTAL_COUNT - avgCount;//随机分配份数
        private static double leftMoney = TOTAL_MONEY; //剩余金额
        private static int leftCount = TOTAL_COUNT;//剩余份数
        
        private static double avgTotal = 0;//均值列表总值
        private static double randomTotal = 0;//随机列表总值
        private static int runCount = 0;//运行次数
        private static int minCount = 0;//算法中获得的最小金额的个数
        private static int avgBottomCount = 0;//均值以下的个数
        private static double maxValue, minValue; //算法中获得的最大值和最小值
        
        private static List<Double> list = new ArrayList<>(); //用于存储金额列表
    
        private static int treeTime = 1;//递归次数,超过10次直接返回最小值,防止递归层数过深导致的栈溢出
        
        public static void main(String[] args) {
            System.out.println("倍数为" + setTimes() + ",平均值为" + avgMoney);
            if(!isRight(TOTAL_MONEY, TOTAL_COUNT)) { //如果设置金额和份数不合法则报错
                initAllAvgList();
            } else{
                initAvgList();
                initRandomList();
            }
            if(IS_UPSET) {
                System.out.println("打乱前:" + list); //打印打乱前的金额列表
                Collections.shuffle(list);//打乱列表
                System.out.println("打乱后:" + list); //打印打乱后的金额列表
            } else{
                System.out.println(list); //打印金额列表
            }
            System.out.println("均值总额为" + Math.round(avgTotal) + ",随机总额为" + Math.round(randomTotal));
            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("小于平均值的个数为" + avgBottomCount);
            System.out.println("最小金额的个数为" + minCount);
        }
    
        
        /**
         * 填充真实均值列表
         */
        private static void initAllAvgList() {
            for(int i = 0; i < TOTAL_COUNT; i++) {
                double money = Math.floor(avgMoney * 100) / 100;
                list.add(money);
                avgTotal += money;
                if(money < avgMoney) avgBottomCount++;
                if(Double.doubleToLongBits(money) == Double.doubleToLongBits(MIN_MONEY)) minCount++;
            }
        }
        
        /**
         * 填充浮动均值列表
         */
        private static void initAvgList() {
            for(int i = 0; i < avgCount; i++) {
                double money = getAvgMoney();
                list.add(money);
                avgTotal += money;
                if(money < avgMoney) avgBottomCount++;
                if(Double.doubleToLongBits(money) == Double.doubleToLongBits(MIN_MONEY)) minCount++;
            }
        }
        
        /**
         * 填充随机列表
         */
        private static void initRandomList() {
            for(int i = 0; i < randomCount; i++) {
                double money = getRandomMoney();
                list.add(money);
                randomTotal += money;
                if(money < avgMoney) avgBottomCount++;
                if(Double.doubleToLongBits(money) == Double.doubleToLongBits(MIN_MONEY)) minCount++;
            }
        }
        
        /**
         * 均值上下浮动算法
         * @return 误差均值(均值+均值*浮动比例)
         */
        private static double getAvgMoney() {
            runCount++;
            if(treeTime >= 10) {
                treeTime = 1;
                return MIN_MONEY;
            }
            if (leftCount == 1) {
                return (double) Math.round(leftMoney * 100) /100;
            }
            Random r = new Random();
            double money = avgMoney + (r.nextDouble() * 2 -1) * AVG_FLOAT_SCALE * avgMoney;
            money = money <= MIN_MONEY ? MIN_MONEY : money;
            money = Math.floor(money * 100) / 100;
            if(isRight(leftMoney - money, leftCount - 1)) {
                treeTime = 1;
                leftMoney -= money;
                leftCount--;
                return money;
            } else {//如果不合法则递归调用随机算法,直到合法
                treeTime++;
                return getAvgMoney();
            }
        }
        
        /**
         * 随机算法
         * @return 随机金额(最小金额~当前均值*倍数)
         */
        private static double getRandomMoney() {
            runCount++;
            if(treeTime >= 10) {
                treeTime = 1;
                return MIN_MONEY;
            }
            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)) {
                treeTime = 1;
                leftMoney -= money;
                leftCount--;
                return money;
            } else {//如果不合法则递归调用随机算法,直到合法
                treeTime++;
                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;
        }
    }
  • 相关阅读:
    文件复制
    linux 计划任务
    mysql查询权限的用户名密码
    mysql导入导出及复制
    windowslucene安装配置
    apache+php32位平台安装
    文件移动
    mysql查询权限的用户名密码
    取树状结构的某个值下的所有记录
    今天发生了个有趣的排序
  • 原文地址:https://www.cnblogs.com/kangweifeng/p/8436593.html
Copyright © 2020-2023  润新知