阶梯费用计算(配置化_最小demo)

本文旨在提供一种配置化思路计算阶梯费用,更高级的做法则是通过数据库配置,注册中心等;在表达式上可以采用自定义或者spel表达式等其他方式进行处理;(代码仅展示最小demo,部分不完善地方自行补充)

思路:N个区间对应N个费用模式(费用模式可以根据需要进行扩展);

          先进行第一个区间的值,收集后续区间,然后按照最大区间差值加权

          

目录

一、核心代码

二、工具类DataCompareUtils


一、核心代码



import java.math.BigDecimal;
import java.math.MathContext;
import java.util.ArrayList;
import java.util.List;

/**
 * description:
 */
public class FeeT {
    public static void main(String[] args) {
        /**
         * 如果 value落在区间N,
         *     当前区间则为当前值减去最小值 加权计算
         *     剩余区间则按照区间最大值  加权计算,
         *   1  10 80 -1
         */
        String expression = "(0,10]#(10,20]#(20,100]#(100,";
        String model = "+1#*1#*1#-1";
        String value = "101";
        BigDecimal bigDecimal = getStepFeeItem(expression, model, value);
        System.out.println(bigDecimal.doubleValue());


    }

    private static BigDecimal getStepFeeItem(String expression, String model, String value) {
        BigDecimal bigDecimal = new BigDecimal(0);
        String[] expressionArr = expression.split("#");
        String[] modelArr = model.split("#");
        List<String> expressionA = new ArrayList<>();
        /**
         * 计算第一个区间的值
         */
        bigDecimal = computeFirst(value, bigDecimal, expressionArr, modelArr, expressionA);
        bigDecimal = computeLast(bigDecimal, expressionA);
        return bigDecimal;
    }

    private static BigDecimal computeLast(BigDecimal bigDecimal, List<String> expressionA) {
        for (String s : expressionA) {
            String[] split = s.split("#");
            BigDecimal computeValue = computeValue(BigDecimal.valueOf(Double.parseDouble(maxRange(split[1]))).subtract(BigDecimal.valueOf(Double.parseDouble(minRange(split[1])))), split[0], true);
            bigDecimal = bigDecimal.add(computeValue);
        }
        return bigDecimal;
    }

    private static BigDecimal computeFirst(String value, BigDecimal bigDecimal, String[] expressionArr, String[] modelArr, List<String> expressionA) {
        for (int i = expressionArr.length - 1; i >= 0; i--) {
            if (DataCompareUtils.checkValue(value, expressionArr[i])) {
                BigDecimal computeValue = computeValue(BigDecimal.valueOf(Double.parseDouble(value)).subtract(BigDecimal.valueOf(Double.parseDouble(minRange(expressionArr[i])))), modelArr[i], true);
                bigDecimal = bigDecimal.add(computeValue);
                //如果目标值在遍历区间,则剩余区间则放到另外一个队列中
                for (int j = i - 1; j >= 0; j--) {
                    expressionA.add(new StringBuilder().append(modelArr[j]).append("#").append(expressionArr[j]).toString());
                }
                break;
            }
        }
        return bigDecimal;
    }


    public static String minRange(String expression) {
        String all = expression.replaceAll("[^0-9.,]", "");
        String[] split = all.split(",");
        return split[0];
    }

    public static String maxRange(String expression) {
        String all = expression.replaceAll("[^0-9.,]", "");
        String[] split = all.split(",");
        return split[1];
    }

    public static BigDecimal computeValue(BigDecimal value, String expression, boolean flag) {
        String symbol = expression.replaceAll("[^\\+\\-\\*/]", ""); //+-*/
        String feeValue = expression.replaceAll("[\\+\\-\\*/]", "");// 1
        switch (symbol) {
            case "+":
                return flag ? BigDecimal.valueOf(Double.parseDouble(feeValue)).setScale(4, BigDecimal.ROUND_CEILING) : value.add(BigDecimal.valueOf(Double.parseDouble(feeValue))).setScale(4, BigDecimal.ROUND_CEILING);
            case "-":
                return flag ?BigDecimal.valueOf(Double.parseDouble(feeValue)).multiply(BigDecimal.valueOf(-1)).setScale(4, BigDecimal.ROUND_CEILING): value.subtract(BigDecimal.valueOf(Double.parseDouble(feeValue))).setScale(4, BigDecimal.ROUND_CEILING);
            case "*":
                return value.multiply(BigDecimal.valueOf(Double.parseDouble(feeValue))).setScale(4, BigDecimal.ROUND_CEILING);
            case "/":
                return value.divide(BigDecimal.valueOf(Double.parseDouble(feeValue)), MathContext.DECIMAL64).setScale(4, BigDecimal.ROUND_CEILING);
            default:
                return value;
        }
    }

}

二、工具类DataCompareUtils

数据比较工具,不同区间的值进行比较


import org.apache.commons.lang3.StringUtils;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Pattern;

/**
 * description: 数据比较工具类
 */
public class DataCompareUtils {
    private DataCompareUtils() {
    }


    public static final Map<String, String> SYMBOL_MAP = new HashMap<>();

    static {
        SYMBOL_MAP.put("(,)", "(,)");
        SYMBOL_MAP.put("[,)", "[,)");
        SYMBOL_MAP.put("(,]", "(,]");
        SYMBOL_MAP.put("[,]", "[,]");
        SYMBOL_MAP.put("[,", "[,");
        SYMBOL_MAP.put("(,", "(,");
        SYMBOL_MAP.put(",]", ",]");
        SYMBOL_MAP.put(",)", ",)");
    }

    public static final String SYMBOL_01 = "(,)";
    public static final String SYMBOL_02 = "[,)";
    public static final String SYMBOL_03 = "(,]";
    public static final String SYMBOL_04 = "[,]";
    public static final String SYMBOL_05 = "[,";
    public static final String SYMBOL_06 = "(,";
    public static final String SYMBOL_07 = ",]";
    public static final String SYMBOL_08 = ",)";

    private static final Pattern NUMBER_REG = Pattern.compile("^-?\\d+(\\.\\d+)?$");

    /**
     * 双边校验 返回true说明不符合
     * [4,5] (3,5)
     * 不符合返回false,符合区间返回true
     *
     * @param value
     * @return
     */

    public static boolean checkValue(String value, String config) {
        if (StringUtils.isEmpty(config)) {
            return false;
        }
        config = config.replace(" ", "").replace(",", ",").replace("(", "(").replace("【", "[").replace("】", "]").replace(")", ")").trim();
        config = config.replaceAll("[^0-9.()\\[\\],]", ""); //获取 [3,8]
        String s = config.replaceAll("[^\\[\\]\\(\\),]", "");//获取 []
        if (StringUtils.isEmpty(SYMBOL_MAP.get(s))) {
            return false;
        }
        /**
         * 第一个为值  第二个为配置表达式
         */

        boolean flag = false;
        switch (s) {
            case SYMBOL_01:
                flag = checkLeftNoAndRightNo(value, config);
                break;
            case SYMBOL_02:
                flag = checkLeftAndRightNo(value, config);
                break;
            case SYMBOL_03:
                flag = checkLeftNoAndRight(value, config);
                break;
            case SYMBOL_04:
                flag = checkLeftAndRight(value, config);
                break;
            case SYMBOL_05:
                flag = checkLeft(value, config);
                break;
            case SYMBOL_06:
                flag = checkLeftNo(value, config);
                break;
            case SYMBOL_07:
                flag = checkRight(value, config);
                break;
            case SYMBOL_08:
                flag = checkRightNo(value, config);
                break;
            default:
                break;
        }
        return flag;
    }

    //(5,8)
    public static boolean checkLeftNoAndRightNo(String value, String config) {
        String range = config.replace("(", "").replace(")", "");
        String[] split = range.split(",");
        return checkNoIncludeMin(value, split[0]) && checkNoIncludeMax(value, split[1]);
    }

    //(5,8]
    public static boolean checkLeftNoAndRight(String value, String config) {
        String range = config.replace("(", "").replace("]", "");
        String[] split = range.split(",");
        return checkNoIncludeMin(value, split[0]) && checkIncludeMax(value, split[1]);
    }

    //[5,8)
    public static boolean checkLeftAndRightNo(String value, String config) {
        String range = config.replace("[", "").replace(")", "");
        String[] split = range.split(",");
        return checkIncludeMin(value, split[0]) && checkNoIncludeMax(value, split[1]);
    }

    //[5,8]
    public static boolean checkLeftAndRight(String value, String config) {
        String range = config.replace("[", "").replace("]", "");
        String[] split = range.split(",");
        return checkIncludeMin(value, split[0]) && checkIncludeMax(value, split[1]);
    }

    //(5,
    public static boolean checkLeftNo(String value, String config) {
        String range = config.replace("(", "").replace(",", "");
        return checkNoIncludeMin(value, range);
    }

    //[5,
    public static boolean checkLeft(String value, String config) {
        String range = config.replace("[", "").replace(",", "");
        return checkIncludeMin(value, range);
    }

    //,8)
    public static boolean checkRightNo(String value, String config) {
        String range = config.replace(")", "").replace(",", "");
        return checkNoIncludeMax(value, range);
    }

    //,8]
    public static boolean checkRight(String value, String config) {
        String range = config.replace("]", "").replace(",", "");
        return checkIncludeMax(value, range);
    }


    /**
     * 校验下限 不含 (6,
     *
     * @param value
     * @param target
     * @return
     */
    public static boolean checkNoIncludeMin(String value, String target) {
        if (StringUtils.isEmpty(value) || StringUtils.isEmpty(target)) {
            return false;
        }
        if (BigDecimal.valueOf(Double.parseDouble(value)).compareTo(BigDecimal.valueOf(Double.parseDouble(target))) > 0) {
            return true;
        }
        return false;
    }

    /**
     * 含最小 [6,
     *
     * @param value
     * @param target
     * @return
     */
    public static boolean checkIncludeMin(String value, String target) {
        if (StringUtils.isEmpty(value) || StringUtils.isEmpty(target)) {
            return false;
        }
        if (BigDecimal.valueOf(Double.parseDouble(value)).compareTo(BigDecimal.valueOf(Double.parseDouble(target))) >= 0) {
            return true;
        }
        return false;
    }

    /**
     * 最大包含  ,6]
     *
     * @param value
     * @param target
     * @return
     */
    public static boolean checkIncludeMax(String value, String target) {
        if (StringUtils.isEmpty(value) || StringUtils.isEmpty(target)) {
            return false;
        }
        if (BigDecimal.valueOf(Double.parseDouble(value)).compareTo(BigDecimal.valueOf(Double.parseDouble(target))) <= 0) {
            return true;
        }
        return false;
    }

    /**
     * 不含最大校验    ,6)
     *
     * @param value
     * @param target
     * @return
     */
    public static boolean checkNoIncludeMax(String value, String target) {
        if (StringUtils.isEmpty(value) || StringUtils.isEmpty(target)) {
            return false;
        }
        if (BigDecimal.valueOf(Double.parseDouble(value)).compareTo(BigDecimal.valueOf(Double.parseDouble(target))) < 0) {
            return true;
        }
        return false;
    }

    /**
     * 判断是否为数字
     *
     * @param value
     * @return
     */
    public static boolean checkIsNumber(String value) {
        return NUMBER_REG.matcher(value).matches();
    }

    //\u00A0,\u0020,\u3000
//    1.不间断空格\u00A0,主要用在office中,让一个单词在结尾处不会换行显示,快捷键ctrl+shift+space ;
//2.半角空格(英文符号)\u0020,代码中常用的;
//3.全角空格(中文符号)\u3000,中文文章中使用;
    public static String replaceSpecialEmpty(String value) {
        if (StringUtils.isEmpty(value)) {
            return value;
        }
        return value.replace("\\u00A0", "").replace("\\u0020", "").replace("\\u3000", "");
    }


    public static void main(String[] args) {

        List<String> arrayList = new ArrayList<>();
        arrayList.add("(5,8)");
        arrayList.add("[5,8)");
        arrayList.add("(5,8]");
        arrayList.add("[5,8]");
        arrayList.add("[5,");
        arrayList.add("(5,");
        arrayList.add(",8]");
        arrayList.add(",8)");
        String target = "8.01";
        for (String s : arrayList) {
            boolean checked = checkValue(target, s);
            System.out.printf("s:%s ,%s, %s", s, target, checked);
            System.out.println();
        }

    }

}

三、效果

String expression = "(0,10]#(10,20]#(20,100]#(100,";
String model = "*1#*2#*2#+1";
String value = "101";

1+80*2+10*2+10

1+160+20+10=191

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值