java数据计算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 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;
        }
    }

}

你可能感兴趣的:(java)