您好,登錄后才能下訂單哦!
方式一
public class Test { public static void main(String[] args) throws Exception { String str = "(a or b) and c"; str = str.replaceAll("or", "||"); str = str.replaceAll("and", "&&"); System.out.println(str); ScriptEngineManager manager = new ScriptEngineManager(); ScriptEngine engine = manager.getEngineByName("js"); engine.put("a",true); engine.put("b",false); engine.put("c",true); Object result = engine.eval_r(str); System.out.println("結果類型:" + result.getClass().getName() + ",計算結果:" + result); } }
這種方式使用js的方式進行運算,使用較簡單,但是當運算double類型的四則運算時結果會出現循環小數,運算結果會出現問題.
方式二(能夠保證四則運算精度):
/** * @Project: BizRule * @File: org.coffeesweet.util.MathExpress.java * @Author: coffeesweet * @Date: 2011-3-28 * @Description: 2011 coffeesweet Inc. All rights reserved. */ package org.coffeesweet.util; import java.math.BigDecimal; import java.math.MathContext; import java.math.RoundingMode; import java.util.ArrayList; import java.util.LinkedList; import java.util.List; import java.util.StringTokenizer; import java.util.regex.Matcher; import java.util.regex.Pattern; /** * @author coffeesweet * +,-,*,/四則運算的表達式逆波蘭解析計算類,精確計算,應用BigDecimal類處理 * 支持負數,但規范除整個表達式第一個數為負數時可以不出現在'('后,其它表達式中間任何位置的 * 負數必須出現在'('后,即:用括號括起來。比如:-3+(-2+1)*10或-3+((-2)+1)*10或(-3)+(-2+1)*10或(-3)+((-2)+1)*10 */ public class MathExpress { /** * + */ private final static String OP1 = "+"; /** * - */ private final static String OP2 = "-"; /** * * */ private final static String OP3 = "*"; /** * / */ private final static String OP4 = "/"; /** * ^ */ // private final static String OP5 = "^"; /** * % */ // private final static String OP6 = "%"; /** * ( */ private final static String OPSTART = "("; /** * ) */ private final static String OPEND = ")"; /** * !用來替代負數前面的'-' */ // private final static String NEGATIVESING = "!"; /** * !用來替代負數前面的'+' */ // private final static String PLUSSING = "@"; /** * '#'用來代表運算級別最低的特殊字符 */ // private final static String LOWESTSING = "#"; //最原始的四則運算式 private String expBase; //經過初始化處理后的四則運算式 private String expInited; //精度 private int precision=10; //取舍模式 private RoundingMode roundingMode=RoundingMode.HALF_UP; //精度上下文 private MathContext mc; //四則運算解析 private List<String> expList = new ArrayList<String>(); //存放逆波蘭表達式 private List<String> rpnList = new ArrayList<String>(); public MathExpress(){ } public MathExpress(String expBase) { init(expBase,this.precision,this.roundingMode); } public MathExpress(String expBase,int precision,RoundingMode roundingMode){ init(expBase,precision,roundingMode); } public void init(String expBase,int precision,RoundingMode roundingMode){ this.expBase = expBase; this.precision = precision; this.roundingMode = roundingMode; this.mc = new MathContext(precision,roundingMode); this.expInited = initExpress(expBase); StringTokenizer st = new StringTokenizer(this.expInited,"+-*/^%()",true); while(st.hasMoreElements()){ this.expList.add(st.nextElement().toString().trim()); } this.rpnList = initRPN(this.expList); } /** * @return the expBase */ public String getExpBase() { return expBase; } /** * @param expBase the expBase to set */ public void setExpBase(String expBase) { this.expBase = expBase; } /** * @return the expInited */ public String getExpInited() { return expInited; } /** * @param expInited the expInited to set */ public void setExpInited(String expInited) { this.expInited = expInited; } /** * @return the precision */ public int getPrecision() { return precision; } /** * @param precision the precision to set */ public void setPrecision(int precision) { this.precision = precision; } /** * @return the roundingMode */ public RoundingMode getRoundingMode() { return roundingMode; } /** * @param roundingMode the roundingMode to set */ public void setRoundingMode(RoundingMode roundingMode) { this.roundingMode = roundingMode; } /** * @return the expList */ public List<String> getExpList() { return expList; } /** * @param expList the expList to set */ public void setExpList(List<String> expList) { this.expList = expList; } /** * @return the rpnList */ public List<String> getRpnList() { return rpnList; } /** * @param rpnList the rpnList to set */ public void setRpnList(List<String> rpnList) { this.rpnList = rpnList; } /** * @return the mc */ public MathContext getMc() { return mc; } /** * @param mc the mc to set */ public void setMc(MathContext mc) { this.mc = mc; } /** * 去除空白字符和在負號'-'前加'0',便于后面的StringTokenizer * @param exp * @return */ private static String initExpress(String exp){ String reStr = null; reStr = exp.replaceAll("\\s", ""); if(reStr.startsWith("-")){ reStr = "0"+reStr; } reStr = reStr.replaceAll("\\(\\-", "(0-"); return reStr; } /** * 是否是整數或是浮點數,但默認-05.15這種也認為是正確的格式 * @param str * @return */ private boolean isNumber(String str){ Pattern p = Pattern.compile("^(-?\\d+)(\\.\\d+)?$"); Matcher m = p.matcher(str); boolean isNumber = m.matches(); return isNumber; } /** * 設置優先級順序()設置與否無所謂 * @param sign * @return */ private int precedence(String str){ char sign = str.charAt(0); switch(sign){ case '+': case '-': return 1; case '*': case '/': return 2; case '^': case '%': return 3; case '(': case ')': // case '#': default: return 0; } } /** * 轉變為逆波蘭表達式 * @param strList * @return */ public List<String> initRPN(List<String> strList){ List<String> returnList = new ArrayList<String>(); //用來存放操作符的棧 Stack stack = new Stack(); // stack.push(LOWESTSING); int length = strList.size(); for(int i=0;i<length;i++ ){ String str = strList.get(i); if(isNumber(str)){ returnList.add(str); }else{ if(str.equals(OPSTART)){ //'('直接入棧 stack.push(str); }else if(str.equals(OPEND)){ //')' //進行出棧操作,直到棧為空或者遇到第一個左括號 while (!stack.isEmpty()) { //將棧頂字符串做出棧操作 String tempC = stack.pop(); if (!tempC.equals(OPSTART)) { //如果不是左括號,則將字符串直接放到逆波蘭鏈表的最后 returnList.add(tempC); }else{ //如果是左括號,退出循環操作 break; } } }else{ if (stack.isEmpty()) { //如果棧內為空 //將當前字符串直接壓棧 stack.push(str); }else{ //棧不空,比較運算符優先級順序 if(precedence(stack.top())>=precedence(str)){ //如果棧頂元素優先級大于當前元素優先級則 while(!stack.isEmpty() && precedence(stack.top())>=precedence(str)){ returnList.add(stack.pop()); } } stack.push(str); } } } } //如果棧不為空,則將棧中所有元素出棧放到逆波蘭鏈表的最后 while (!stack.isEmpty()) { returnList.add(stack.pop()); } return returnList; } /** * 計算逆波蘭表達式 * @param rpnList * @return */ public String caculate(List<String> rpnList){ Stack numberStack = new Stack(); int length=rpnList.size(); for(int i=0;i<length;i++){ String temp=rpnList.get(i); if(isNumber(temp)){ numberStack.push(temp); }else{ BigDecimal tempNumber1 = new BigDecimal(numberStack.pop(),this.mc); BigDecimal tempNumber2 = new BigDecimal(numberStack.pop(),this.mc); BigDecimal tempNumber = new BigDecimal("0",this.mc); if(temp.equals(OP1)){ tempNumber=tempNumber2.add(tempNumber1); }else if(temp.equals(OP2)){ tempNumber=tempNumber2.subtract(tempNumber1); }else if(temp.equals(OP3)){ tempNumber=tempNumber2.multiply(tempNumber1); }else if(temp.equals(OP4)){ tempNumber=tempNumber2.divide(tempNumber1, precision, roundingMode); } numberStack.push(tempNumber.toString()); } } return numberStack.pop(); } /** * 按照類的缺省參數進行計算 * @return */ public String caculate(){ return caculate(this.rpnList); } /** * 數字條件表達式精確比較 * eg: "3.0>2" "1<5" "1==5" "1!=5" "(1.0+2)>3" "((-0.9+3)>=2. 1)" * 不支持&&,||等連接符 * @param str * @return */ public static boolean compareTo(String strParm){ boolean reBoolean = false; boolean isParentheses = false;//標記是否有()括上整個字符串 String str = initExpress(strParm); Pattern p = Pattern.compile("^\\([\\s\\S]*\\)$"); Matcher m = p.matcher(str); isParentheses = m.matches(); if(-1==str.indexOf(">=")&&-1==str.indexOf("<=")&&-1==str.indexOf("==")&&-1==str.indexOf("!=")){ if(-1==str.indexOf(">")&&-1==str.indexOf("<")) throw new IllegalArgumentException("異常:條件表達式不正確!"); } if(-1 != str.indexOf(">=")){ String[] strTemps = str.split(">="); if(isParentheses){ strTemps[0] = strTemps[0] + ")"; strTemps[1] = "(" + strTemps[1]; } int r = new BigDecimal((new MathExpress(strTemps[0]).caculate())).compareTo(new BigDecimal((new MathExpress(strTemps[1]).caculate()))); if( -1 == r ){ reBoolean = false; }else{ reBoolean = true; } }else if(-1 != str.indexOf("<=")){ String[] strTemps = str.split("<="); if(isParentheses){ strTemps[0] = strTemps[0] + ")"; strTemps[1] = "(" + strTemps[1]; } int r = new BigDecimal((new MathExpress(strTemps[0]).caculate())).compareTo(new BigDecimal((new MathExpress(strTemps[1]).caculate()))); if( 1 == r ){ reBoolean = false; }else{ reBoolean = true; } }else if(-1 != str.indexOf("==")){ String[] strTemps = str.split("=="); if(isParentheses){ strTemps[0] = strTemps[0] + ")"; strTemps[1] = "(" + strTemps[1]; } int r = new BigDecimal((new MathExpress(strTemps[0]).caculate())).compareTo(new BigDecimal((new MathExpress(strTemps[1]).caculate()))); if( 0 == r ){ reBoolean = true; }else{ reBoolean = false; } }else if(-1 != str.indexOf("!=")){ String[] strTemps = str.split("!="); if(isParentheses){ strTemps[0] = strTemps[0] + ")"; strTemps[1] = "(" + strTemps[1]; } int r = new BigDecimal((new MathExpress(strTemps[0]).caculate())).compareTo(new BigDecimal((new MathExpress(strTemps[1]).caculate()))); if( 0 != r ){ reBoolean = true; }else{ reBoolean = false; } }else if((-1 != str.indexOf(">")) && (-1 == str.indexOf("="))){ String[] strTemps = str.split(">"); if(isParentheses){ strTemps[0] = strTemps[0] + ")"; strTemps[1] = "(" + strTemps[1]; } int r = new BigDecimal((new MathExpress(strTemps[0]).caculate())).compareTo(new BigDecimal((new MathExpress(strTemps[1]).caculate()))); if( 1 == r ){ reBoolean = true; }else{ reBoolean = false; } }else if((-1 != str.indexOf("<")) && (-1 == str.indexOf("="))){ String[] strTemps = str.split("<"); if(isParentheses){ strTemps[0] = strTemps[0] + ")"; strTemps[1] = "(" + strTemps[1]; } int r = new BigDecimal((new MathExpress(strTemps[0]).caculate())).compareTo(new BigDecimal((new MathExpress(strTemps[1]).caculate()))); if( -1 == r ){ reBoolean = true; }else{ reBoolean = false; } } return reBoolean; } public static void main(String...args){ // MathExpress me = new MathExpress("-(-0.5+0.1)*10+2",10,RoundingMode.HALF_UP); // System.out.println(me.getExpList()); // List<String> tempList = me.initRPN(me.getExpList()); // System.out.println(tempList); // String resultStr = me.caculate(tempList); // System.out.println(resultStr); MathExpress me = new MathExpress("-(-1.5000000003+0.1)*10+2"); String resultStr = me.caculate(); BigDecimal bd = new BigDecimal(resultStr); BigDecimal bd2 = bd.setScale(2, RoundingMode.HALF_UP); System.out.println(me.caculate()); System.out.println(bd.toString()); System.out.println(bd.scale()); System.out.println(bd2.toString()); System.out.println(bd2.scale()); // System.out.println("------------------------------------"); // Pattern p = Pattern.compile("^\\([\\s\\S]*\\)$");//匹配類似以'('開頭')'結尾的字符串 // Matcher m = p.matcher("(2. 0>2.22)"); // System.out.println(m.matches()); boolean reBoolean = MathExpress.compareTo("((-8.0+3)>=2. 1)"); System.out.println(reBoolean); } /** * 棧 */ private class Stack { LinkedList<String> stackList = new LinkedList<String>(); public Stack() { } /** * 入棧 * @param expression */ public void push(String expression) { stackList.addLast(expression); } /** * 出棧 * @return */ public String pop() { return stackList.removeLast(); } /** * 棧頂元素 * @return */ public String top() { return stackList.getLast(); } /** * 棧是否為空 * @return */ public boolean isEmpty() { return stackList.isEmpty(); } } }
以上這篇java代碼執行字符串中的邏輯運算方法就是小編分享給大家的全部內容了,希望能給大家一個參考,也希望大家多多支持億速云。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。