這個表達式引擎只有短短的100多行,卻能實現包括加減乘除、括號優先級在內的運算,能夠在「處理表達式」函數中自行擴展想要處理的算法。這裏面算法的難點主要在於如何實如今多級括號存在的狀況下,能取出最外層的一對括號,「成對處理」函數能夠普遍的應用在爬蟲、數據抓取的軟件中。java
很少說,先上源碼算法
import java.util.ArrayList; import java.util.Hashtable; import java.util.List; import java.util.regex.Matcher; import java.util.regex.Pattern; public class Calculate { private Hashtable<String, Object> 堆棧值 = new Hashtable<>(); private int 表達式遊標 = 0; public static List<String> 成對處理(String code, String start, String end) { List<String> subResult = new ArrayList<>(); String temp = ""; String nextLevelCode = ""; int level = 0; for (char codeChar : code.toCharArray()) { temp += codeChar; if (temp.endsWith(end)) { level--; if (level == 0) { subResult.add(nextLevelCode.toString()); nextLevelCode = ""; } } if (level != 0) { nextLevelCode += codeChar; } if (temp.endsWith(start)) { level++; } } return subResult; } public static List<String> 前置處理(String code, String front) { front = front.replace("+", "\\+").replace("-", "\\-"); return getMatchList(code, front + "[_a-zA-Z\\u4E00-\\u9FA5]+[0-9]*"); } public static List<String> 後置處理(String code, String back) { back = back.replace("+", "\\+").replace("-", "\\-"); return getMatchList(code, "[_a-zA-Z\\u4E00-\\u9FA5]+[0-9]*" + back); } public static List<String> 運算處理(String code, String calc) { calc = calc.replace("+", "\\+").replace("*", "\\*").replace("-", "\\-"); return getMatchList(code, "[_a-zA-Z0-9\\u4E00-\\u9FA5]+[\\.]*[0-9]*" + calc + "[_a-zA-Z\\u4E00-\\u9FA5]*[0-9]*[\\.]*[0-9]*"); } public Object 處理表達式(String 表達式) throws Exception { List<String> 子表達式列表 = new ArrayList(); // 先運算括號中的內容 子表達式列表 = 成對處理(表達式, "(", ")"); if (子表達式列表.size() != 0) { for (String 子表達式 : 子表達式列表) { Object 子表達式值 = 處理表達式(子表達式); String 遊標鍵 = "_V" + (表達式遊標++); 堆棧值.put(遊標鍵, 子表達式值); 表達式 = 表達式.replace("(" + 子表達式 + ")", 遊標鍵); } return 處理表達式(表達式); } 表達式 = 表達式.replace(" ", ""); // 運算乘法 if (表達式.contains("*")) 子表達式列表 = 運算處理(表達式, "*"); if (子表達式列表.size() != 0) { for (String 子表達式 : 子表達式列表) { String 乘數 = 子表達式.split("\\*")[0]; String 被乘數 = 子表達式.split("\\*")[1]; if (乘數.startsWith("_V")) 乘數 = 堆棧值.get(乘數).toString(); if (被乘數.startsWith("_V")) 被乘數 = 堆棧值.get(被乘數).toString(); Object 子表達式值 = Double.parseDouble(乘數) * Double.parseDouble(被乘數); String 遊標鍵 = "_V" + (表達式遊標++); 堆棧值.put(遊標鍵, 子表達式值); 表達式 = 表達式.replace(子表達式, 遊標鍵); } return 處理表達式(表達式); } // 運算除法 if (表達式.contains("/")) 子表達式列表 = 運算處理(表達式, "/"); if (子表達式列表.size() != 0) { for (String 子表達式 : 子表達式列表) { String 乘數 = 子表達式.split("/")[0]; String 被乘數 = 子表達式.split("/")[1]; if (乘數.startsWith("_V")) 乘數 = 堆棧值.get(乘數).toString(); if (被乘數.startsWith("_V")) 被乘數 = 堆棧值.get(被乘數).toString(); Object 子表達式值 = Double.parseDouble(乘數) / Double.parseDouble(被乘數); String 遊標鍵 = "_V" + (表達式遊標++); 堆棧值.put(遊標鍵, 子表達式值); 表達式 = 表達式.replace(子表達式, 遊標鍵); } return 處理表達式(表達式); } // 運算加法 if (表達式.contains("+")) 子表達式列表 = 運算處理(表達式, "+"); if (子表達式列表.size() != 0) { for (String 子表達式 : 子表達式列表) { String 乘數 = 子表達式.split("\\+")[0]; String 被乘數 = 子表達式.split("\\+")[1]; if (乘數.startsWith("_V")) 乘數 = 堆棧值.get(乘數).toString(); if (被乘數.startsWith("_V")) 被乘數 = 堆棧值.get(被乘數).toString(); Object 子表達式值 = Double.parseDouble(乘數) + Double.parseDouble(被乘數); String 遊標鍵 = "_V" + (表達式遊標++); 堆棧值.put(遊標鍵, 子表達式值); 表達式 = 表達式.replace(子表達式, 遊標鍵); } return 處理表達式(表達式); } // 運算加法 if (表達式.contains("-")) 子表達式列表 = 運算處理(表達式, "-"); if (子表達式列表.size() != 0) { for (String 子表達式 : 子表達式列表) { String 乘數 = 子表達式.split("\\-")[0]; String 被乘數 = 子表達式.split("\\-")[1]; if (乘數.startsWith("_V")) 乘數 = 堆棧值.get(乘數).toString(); if (被乘數.startsWith("_V")) 被乘數 = 堆棧值.get(被乘數).toString(); Object 子表達式值 = Double.parseDouble(乘數) - Double.parseDouble(被乘數); String 遊標鍵 = "_V" + (表達式遊標++); 堆棧值.put(遊標鍵, 子表達式值); 表達式 = 表達式.replace(子表達式, 遊標鍵); } return 處理表達式(表達式); } // 若是到最後是一個變量,則直接返回變量值 if (表達式.matches("_V[0-9]+")) { return 堆棧值.get(表達式).toString(); } throw new Exception("沒法處理的表達式:" + 表達式); } public static List<String> getMatchList(String managers, String match) { List<String> ls = new ArrayList<String>(); Pattern pattern = Pattern.compile(match); Matcher matcher = pattern.matcher(managers); while (matcher.find()) ls.add(matcher.group()); return ls; } }
public class Test { public static void main(String args[]) throws Exception{ String 表達式="100.25+ (100 /( 25+ 12.5*2))+50/(23+(1+1))"; System.out.println(new Calculate().處理表達式(表達式)); } }輸出結果:104.25