歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
您现在的位置: Linux教程網 >> UnixLinux >  >> Linux編程 >> Linux編程

Java高精度四則運算(無括號限制)

Java高精度四則運算(無括號限制)

package cn.skyatom.common;
 
import java.math.BigDecimal;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
 
/**
 * 基礎四則運算
 *
 * @author ZWK
 */
public class Arithmetic {
 
    private static String getUUID() {
        return java.util.UUID.randomUUID().toString().replaceAll("-", "");
    }
 
    public static void main(String[] args) throws Exception {
        java.util.Map<String, BigDecimal> values = new java.util.HashMap<String, BigDecimal>();
        BigDecimal AAF = new BigDecimal(5.5);
        BigDecimal BCCC = new BigDecimal(8);
        BigDecimal QQC = new BigDecimal(-8.33);
        BigDecimal DCC = new BigDecimal(2);
        BigDecimal EE = new BigDecimal(23);
        BigDecimal BF = new BigDecimal(2.5);
        BigDecimal A1 = new BigDecimal(12);
        BigDecimal A2 = new BigDecimal(4);
        BigDecimal A3 = new BigDecimal(5);
        BigDecimal A4 = new BigDecimal(15);
 
        values.put("AAF", AAF);
        values.put("BCCC", BCCC);
        values.put("QQC", QQC);
        values.put("DCC", DCC);
        values.put("EE", EE);
        values.put("BF", BF);
        values.put("A1", A1);
        values.put("A2", A2);
        values.put("A3", A3);
        values.put("A4", A4);
 
//       
//        values.put("B1", 4F);
//        values.put("B2", 15f);
//        values.put("B3", 55f);
//        values.put("B4", 2f);
//        values.put("B5", 5f);
        String str = "AAF  * BCCC + QQC  /DCC-EE*BF+( A1*(A2/(A3+A4))  ) ";//5.5*8 + (-8.33)/2 - 23*2.5 + (12*(4/(5+15)) )
        //String str = "B1  * B2 + B3 -B4/  B5 ";//去空白
        //BigDecimal v = getArithmeticValue(str, values);
        System.out.println("結果為:" + getArithmeticFloatValue(str, values));
    }
 
    /**
    * 執行運算,獲取表達式的結果。float值
    *
    * @param str
    * @param values
    * @return
    * @throws Exception
    */
    public static float getArithmeticFloatValue(String str, java.util.Map<String, BigDecimal> values) throws Exception {
        return getArithmeticValue(str, values).floatValue();
    }
 
    public static int getArithmeticIntValue(String str, java.util.Map<String, BigDecimal> values) throws Exception {
        return getArithmeticValue(str, values).intValue();
    }
 
    public static long getArithmeticLongValue(String str, java.util.Map<String, BigDecimal> values) throws Exception {
        return getArithmeticValue(str, values).longValue();
    }
 
    /**
    * 替換括號
    *
    * @param str
    * @param values
    * @return 當所有替換完成,null,反之返回替換的字符串
    */
    private static String replaceBrackets(String str, java.util.Map<String, BigDecimal> values) {
        String v = "";
        String tmp = null;//臨時字符串值
        Pattern patt = Pattern.compile("\\(([A-Za-z0-9\\.\\*\\+\\-/]*?)\\)", Pattern.DOTALL);
        Matcher mat = patt.matcher(str);
        if (mat.find()) {
            tmp = mat.group(1);
        }
        if (tmp != null) {
            String uuid = getUUID();
            BigDecimal value = getBasicArithmeticValue(tmp, values);
            str = str.replace("(" + tmp + ")", uuid);
            values.put(uuid, value);
            v = str;
            v = replaceBrackets(v, values);
        } else {
            v = str;
        }
        return v;
    }
 
    /**
    * 執行運算,獲取表達式的結果
    *
    * @param str 表達式字符串
    * @param values 值存儲表
    * @return 返回運算值
    * @throws java.lang.Exception 運算格式錯誤時,拋出異常
    */
    public static BigDecimal getArithmeticValue(String str, java.util.Map<String, BigDecimal> values) throws Exception {
        str = str.replaceAll("\\s*", "");//去空白
        String s = replaceBrackets(str, values);
        if (s != null || !s.trim().equals("")) {
            str = s;
        }
        return getBasicArithmeticValue(str, values);
    }
 
    /**
    * 基本四則運算
    *
    * @param str 基礎四則運算
    * @param values 值存儲表
    * @return
    */
    private static BigDecimal getBasicArithmeticValue(String str, java.util.Map<String, BigDecimal> values) {
        str = multiReg(str, values);
        str = divReg(str, values);
        java.util.List<Boolean> signs = getPlusReduceSign(str);//獲取符號
        java.util.List<String> valuesign = getValueSign(str);//替換符號
        BigDecimal v = getValue(valuesign, signs, values);
        return v;
    }
 
    /**
    * 獲取結果
    *
    * @param valuesign 值替換符號
    * @param signs 符號
    * @param values 值存儲表
    * @return
    */
    private static BigDecimal getValue(java.util.List<String> valuesign, java.util.List<Boolean> signs, java.util.Map<String, BigDecimal> values) {
        BigDecimal value = values.get(valuesign.get(0));
        for (int i = 0; i < signs.size(); i++) {
            if (signs.get(i)) {
                value = value.add(values.get(valuesign.get(i + 1)));
                //value += values.get(valuesign.get(i + 1));
            } else {
                value = value.subtract(values.get(valuesign.get(i + 1)));
                //value -= values.get(valuesign.get(i + 1));
            }
        }
        return value;
    }
 
    /**
    * 獲取替換的符號
    *
    * @param str 待匹配的字符串
    * @return 返回 替換的值符號
    */
    private static java.util.List<String> getValueSign(String str) {
        java.util.List<String> list = new java.util.ArrayList<String>();
        Pattern patt = Pattern.compile("([a-zA-Z0-9]*{1})", Pattern.DOTALL);
        Matcher mat = patt.matcher(str);
        while (mat.find()) {
            if (mat.group(1).trim().equals("")) {
                continue;
            }
            list.add(mat.group(1));
        }
        return list;
    }
 
    /**
    * 獲取加減符號
    *
    * @param str 待匹配的字符串
    * @return 返回 符號順序,加號為true,減號為false
    */
    private static java.util.List<Boolean> getPlusReduceSign(String str) {
        java.util.List<Boolean> list = new java.util.ArrayList<Boolean>();
        Pattern patt = Pattern.compile("([a-zA-Z0-9]*{1}([+|-])[a-zA-Z0-9]*{1})", Pattern.DOTALL);
        Matcher mat = patt.matcher(str);
        while (mat.find()) {
            if (mat.group(2).trim().equals("+")) {
                list.add(true);
            } else {
                list.add(false);
            }
        }
        return list;
    }
 
    /**
    * 乘法的正則
    *
    * @param str 運算表達式字符串
    * @param values 值存儲表
    * @return 返回重構後的字符串
    */
    private static String multiReg(String str, java.util.Map<String, BigDecimal> values) {
        Pattern patt = Pattern.compile("([a-zA-Z0-9]*{1}\\*[a-zA-Z0-9]*{1})", Pattern.DOTALL);
        Matcher mat = patt.matcher(str);
        while (mat.find()) {
            str = excMultiplication(str, mat.group(1), values);
        }
        return str;
    }
 
    /**
    * 除法的正則
    *
    * @param str 運算表達式字符串
    * @param values 值存儲表
    * @return 返回重構後的字符串
    */
    private static String divReg(String str, java.util.Map<String, BigDecimal> values) {
        Pattern patt = Pattern.compile("([a-zA-Z0-9]*{1}\\/[a-zA-Z0-9]*{1})", Pattern.DOTALL);
        Matcher mat = patt.matcher(str);
        while (mat.find()) {
            str = excDivsion(str, mat.group(1), values);
        }
        return str;
    }
 
    /**
    * 計算乘法
    *
    * @param str 全部的運算字符串
    * @param value 計算乘法的字符串
    * @param map 值存儲表
    * @return 返回重構後的字符串
    */
    private static String excMultiplication(String str, String value, java.util.Map<String, BigDecimal> map) {
        String vs[] = value.split("\\*");
        BigDecimal v1 = map.get(vs[0]);
        BigDecimal v2 = map.get(vs[1]);
        BigDecimal x = v1.multiply(v2);
        map.remove(vs[0]);
        map.remove(vs[1]);
        String uuid = getUUID();
        map.put(uuid, x);
        str = str.replace(value, uuid);
        return str;
    }
 
    /**
    * 計算出發
    *
    * @param str 全部的運算字符串
    * @param value 計算乘法的字符串
    * @param map 值存儲表
    * @return 返回重構後的字符串
    */
    private static String excDivsion(String str, String value, java.util.Map<String, BigDecimal> map) {
        String vs[] = value.split("\\/");
        BigDecimal v1 = map.get(vs[0]);
        BigDecimal v2 = map.get(vs[1]);
        BigDecimal x = v1.divide(v2);
        map.remove(vs[0]);
        map.remove(vs[1]);
        String uuid = getUUID();
        map.put(uuid, x);
        str = str.replace(value, uuid);
        return str;
    }
}

最近在開發公司的績效系統,老板又很摳門,不想購買市面上的績效系統。。於是乎,苦逼的我又開始了苦逼的編程……

系統裡面涉及到報表,而各員工間的績效以及實發工資的算法每隔一段時間就會更新,所以不可能做到將算法寫進源碼編譯,需要報表公式進行計算(當然,報表公式系統需要另行開發,這裡不描述)。

以上是JAVA代碼,其思想是將公式字中的參數當作字符串來看待,並不是當作純粹的數字。每次運算時,只進行二元運算,運算之後將數據保存,再刪除原數據表中的數據。如此循環,無需考慮括號的限制了。

在實現代碼時,考慮了直接使用float或者是double類型,但是在最終顯示結果是,兩個類型精度都會產生精度上的丟失,所以最終考慮使用BigDecimal類型,也算是做長期運行考慮吧。

其中有很多需要優化的地方,敢興趣的朋友可以留言交流……

Copyright © Linux教程網 All Rights Reserved