tim工具包-MyMath 計算工具

相關文章:

java 數學計算工具

java 對數學計算的使用性上還是比較麻煩的,遇到大量數據計算複雜的計算公式則會頻發問題。接下來我們來統計一下在java中經常會遇到的計算問題

  • 科學計數法
  • 保留小數點問題
  • 複雜公式處理麻煩
  • 除數爲零

案例:

比如說我需要計算一下數據

案例1

100*2000/20*(20-10)

使用java原生BigDecimal來寫計算會非常痛苦,所以封裝了一套工具供大家使用

 public void test(){
        BigDecimal bigDecimal = new BigDecimal(100);
        bigDecimal= bigDecimal.multiply(new BigDecimal(2000));
        bigDecimal=bigDecimal.divide(new BigDecimal(20));
        BigDecimal b2 = new BigDecimal(20);
        BigDecimal b3 = new BigDecimal(10);
        b2 = b2.subtract(b3);
        bigDecimal = bigDecimal.multiply(b2);

        System.out.println(bigDecimal.setScale(2).doubleValue());
    }

使用MyMath 工具寫法

public void myMathTest(){
        MyMath.test("%s*%s/%s*(%s-%s)","100","2000","20","20","10");
    }

不論是代碼可讀性,和代碼量以及維護性功能都是大大提升的

MyMath 功能介紹

MyMath 自動會處理科學計算法,異常數據等。使用的是js計算

  • 普通計算
 String value1= MyMath.test("100*2000/20*(20-10)");
 或者
 String value= MyMath.test("%s*%s/%s*(%s-%s)","100","2000","20","20","10");
  • 布爾計算
boolean b = MyMath.test2("10>=(5-1)");
或者
boolean b1 = MyMath.test2("%s>=(%s-%s)", "10", "5", "1");
  • 得分計算

得分計算如果都不滿足條件則返回0分

String score = MyMath.getScore("Math.abs(%s-%s)<=10:10,Math.abs(%s-%s)<=15:5", "10", "20");

結果得10分
計算已,號做分割。從做往右依次計算。如果滿足條件則返回:後面的得分,如果一個都未滿足則返回0分

MyMath 核心代碼

import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;
import java.math.BigDecimal;
import java.text.DecimalFormat;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class MyMath {
    String[] str = {"NaN", "Infinity"};

    static ScriptEngine engine = new ScriptEngineManager().getEngineByName("js");

    /**
     * 判斷
     * (
     *
     * @param str 數學公式
     * @return
     */
    public static boolean test2(String str) {
        str = str.replaceAll("null", "0");
        try {
            if (VerifyUtil.isEmpty(str)) return false;
            str = str.replace("--", "+");
            Object result = engine.eval(str);
            if (result instanceof Boolean)
                return (boolean) result;
        } catch (ScriptException e) {
            e.printStackTrace();
        }
        return false;
    }

    /**
     * 判斷計算
     *
     * @param str  數學佔位符公式
     * @param strs 替換數據
     * @return
     */
    public static boolean test2(String str, String... strs) {
        str = String.format(str, strs);
        return test2(str);
    }

    /**
     * 累加
     *
     * @param baseNum
     * @param num
     * @return
     */
    public static String append(String baseNum, String num) {
        return MyMath.test(baseNum + "+" + getNumber(num));
    }

    /**
     * 累加
     *
     * @param baseNum
     * @param key
     * @return
     */
    public static String append(String baseNum, Map<String, Object> param, String key) {
        if (VerifyUtil.isEmpty(param)) return "0";
        return append(baseNum, getNumber(param.get(key)));
    }


    public static String getNumber(Object object) {
        if (VerifyUtil.isEmpty(object)) return "0";
        return object + "";
    }

    /**
     * 判斷
     *
     * @param str 數學公式
     * @return
     */
    public static boolean isInt(String str) {
        str = str.replaceAll("null", "0");
        if (VerifyUtil.isEmpty(str)) return false;
        str = str.replace("--", "+");
        Object result = null;
        try {
            result = engine.eval(str);
        } catch (ScriptException e) {
            e.printStackTrace();
            return false;
        }
        if (result instanceof Boolean)
            return (boolean) result;
        return false;
    }

    /**
     * 4位小數點
     *
     * @param str 數學公式
     * @return
     */
    public static String test(String str) {
        return endMath(str, "###0.0000");
    }

    /**
     * 計算得出結果
     *
     * @param str  佔位符公式
     * @param strs 替換值
     * @return
     */
    public static String test(String str, String... strs) {
        str = String.format(str, strs);
        return test(str);
    }

    /**
     * 轉換整數字符串,科學計算法也可以轉換
     *
     * @param str
     * @return
     */
    public static String tesInt(String str) {
        return endMath(str, "###0");
    }

    /**
     * 8位小數點
     *
     * @param str
     * @return
     */
    public static String end8(String str) {
        return endMath(str, "###0.00000000");
    }

    /**
     * 保留小數點計算
     *
     * @param str     佔位符公式
     * @param toFixed 保留小數點數
     * @param strs    替換值
     * @return
     */
    public static String test(String str, int toFixed, String... strs) {
        str = String.format(str, strs);
        return test(str, toFixed);
    }

    /**
     * 拋出異常計算,用來定位做了什麼處理
     *
     * @param str     佔位符公式
     * @param toFixed 保留小數位數
     * @param strs    替換值
     * @return
     * @throws MathException 拋出異常,包含計算錯誤公式
     */
    public static String testMathException(String str, int toFixed, String... strs) throws MathException {
        str = String.format(str, strs);
        return testException(str, toFixed);
    }

    /**
     * 拋出異常計算,用來定位做了什麼處理
     *
     * @param str     計算公式
     * @param toFixed 保留小數位
     * @return
     * @throws MathException
     */
    public static String testException(String str, int toFixed) throws MathException {
        str = str.replaceAll("null", "0");
        if (VerifyUtil.isEmpty(str)) return "0";
        str = str.replace("--", "+");
        Object result = 0;
        try {
            result = engine.eval(str);
            DecimalFormat decimalFormat = new DecimalFormat("###0.0000");//格式化設置
            result = decimalFormat.format(result);
            if (isInteger(result + "")) {
                BigDecimal bigDecimal = new BigDecimal(result + "");
                result = bigDecimal.setScale(toFixed, BigDecimal.ROUND_HALF_UP).toPlainString();
            }
        } catch (ScriptException e) {
            throw new MathException(str);
        }
        return isNumber(result + "");
    }

    /**
     * 普通計算保留小數位
     *
     * @param str     計算公式
     * @param toFixed 保留小數位
     * @return
     */
    public static String test(String str, int toFixed) {
        str = str.replaceAll("null", "0");
        if (VerifyUtil.isEmpty(str)) return "0";
        str = str.replace("--", "+");
        Object result = 0;
        try {
            result = engine.eval(str);
            DecimalFormat decimalFormat = new DecimalFormat("###0.0000");//格式化設置
            result = decimalFormat.format(result);
            if (isInteger(result + "")) {
                BigDecimal bigDecimal = new BigDecimal(result + "");
                result = bigDecimal.setScale(toFixed, BigDecimal.ROUND_HALF_UP).toPlainString();
            }
        } catch (ScriptException e) {
            System.out.println("報錯公式====  " + str);
            e.printStackTrace();
        }
        return isNumber(result + "");
    }

    /**
     * 是否是數字
     *
     * @param num
     * @return
     */
    public static String isNumber(String num) {
        if (isInteger(num)) {
            if (MyMath.test2(num + "==0")) return "0";
            return num;
        }
        return "0";
    }

    /**
     * 判斷是否是計算數據類型
     *
     * @param obj
     * @return
     */
    public static boolean isInteger(Object obj) {
        String str = obj + "";
        return match("^(-)?[0-9]+(\\.[0-9]+)?$", str);
    }

    /**
     * 是否有小數點
     *
     * @param str
     * @return
     */
    public static boolean isHavaFixed(String str) {
        return str.contains(".");
    }

    /**
     * @param regex 正則表達式字符串
     * @param str   要匹配的字符串
     * @return 如果str 符合 regex的正則表達式格式,返回true, 否則返回 false;
     */
    public static boolean match(String regex, String str) {
        Pattern pattern = Pattern.compile(regex);
        Matcher matcher = pattern.matcher(str);
        return matcher.matches();
    }

    /**
     * 數據計算指定格式
     *
     * @param str  計算公式
     * @param form 指定格式
     * @return
     */
    public static String endMath(String str, String form) {
        str = str.replaceAll("null", "0");
        if (VerifyUtil.isEmpty(str)) return "0";
        str = str.replace("--", "+");
        Object result = 0;
        try {
            result = engine.eval(str);
            DecimalFormat decimalFormat = new DecimalFormat(form);//防止科學計算
            result = decimalFormat.format(result);
        } catch (ScriptException e) {
            System.out.println("報錯公式====  " + str);
            e.printStackTrace();
        }
        return isNumber(result + "");
    }
    /**
     * @param input
     * @return 判斷是否是使用科學計數法的數字字符串
     */
    public static boolean getScientific(String input) {
        String regx = "^((-?\\d+.?\\d*)[Ee]{1}(-?\\d+))$";//科學計數法正則表達式
        Pattern pattern = Pattern.compile(regx);
        return pattern.matcher(input).matches();
    }
    /**
     * 公式佔比
     * ("Math.abs(%s-%s)<=10:10,Math.abs(%s-%s)<=15:5",  "10","20");
     *
     * @param math
     * @return
     */
    public static String getScore(String math, String... values) {
        String score = "0";
        String[] split = math.split(",");
        for (String s : split) {
            String itemMath = String.format(s, values);
            String[] split1 = itemMath.split(":");
            if (MyMath.test2(split1[0])) {
                score = split1[1];
                return score;
            }
        }
        return score;
    }

    /**
     * 結果計算,帶權重
     * ("Math.abs(%s-%s)<=10:10,Math.abs(%s-%s)<=15:5", 10, "10","20");
     *
     * @param math
     * @return
     */
    public static String getScore(String math, Object weight, String... values) {
        String score = "0";
        String[] split = math.split(",");
        for (String s : split) {
            String itemMath = String.format(s, values);
            String[] split1 = itemMath.split(":");
            if (MyMath.test2(split1[0])) {
                score = split1[1];
                score = MyMath.test(score + "*" + weight);
                return score;
            }
        }
        return score;
    }

    public static void main(String[] args) {
        System.out.println(endMath("30021321321.332323", "#0.00"));
//        System.out.println(test("(1+3)/10*10"));

//		Double double1 = 123456789.123456789;
//		Double double1 = 1.2345678912345679E8;
//		DecimalFormat decimalFormat = new DecimalFormat("#,##0.00");//格式化設置
//		System.out.println(decimalFormat.format(double1));
//		System.out.println(double1);
    }

    public static class MathException extends Exception {
        String excMath;

        public MathException() {

        }

        public MathException(String excMath) {
            this.excMath = excMath;
        }

        public String getExcMath() {
            return excMath;
        }

        public void setExcMath(String excMath) {
            this.excMath = excMath;
        }
    }

}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章