java中實現四則運算代碼_java

來源:互聯網
上載者:User

代碼的思路是通過正則判斷計算每個最小的計算單元。以下是代碼:

import java.math.BigDecimal;import java.util.regex.Matcher;import java.util.regex.Pattern;/** * 計算機工具類 * @author shuqi * @date  2015-7-23 * @version since 1.0 */public class CalculatorUtil {  public static BigDecimal arithmetic(String exp){    if(!exp.matches("\\d+")){      String result = parseExp(exp).replaceAll("[\\[\\]]", "");      return new BigDecimal(result);    }else{      return new BigDecimal(exp);    }  }  /**   * 最小計數單位   *    */  private static String minExp="^((\\d+(\\.\\d+)?)|(\\[\\-\\d+(\\.\\d+)?\\]))[\\+\\-\\*\\/]((\\d+(\\.\\d+)?)|(\\[\\-\\d+(\\.\\d+)?\\]))$";  /**   * 不帶括弧的運算   */  private static String noParentheses="^[^\\(\\)]+$";  /**   * 匹配乘法或者除法   */  private static String priorOperatorExp="(((\\d+(\\.\\d+)?)|(\\[\\-\\d+(\\.\\d+)?\\]))[\\*\\/]((\\d+(\\.\\d+)?)|(\\[\\-\\d+(\\.\\d+)?\\])))";  /**   * 匹配加法和減法   */  private static String operatorExp="(((\\d+(\\.\\d+)?)|(\\[\\-\\d+(\\.\\d+)?\\]))[\\+\\-]((\\d+(\\.\\d+)?)|(\\[\\-\\d+(\\.\\d+)?\\])))";  /**   * 匹配只帶一個括弧的   */  private static String minParentheses="\\([^\\(\\)]+\\)";    /**   * 解析計算四則運算運算式,例:2+((3+4)*2-22)/2*3   * @param expression   * @return   */  private static String parseExp(String expression){    //方法進入 先替換空格,在去除運算兩邊的()號    expression=expression.replaceAll("\\s+", "").replaceAll("^\\(([^\\(\\)]+)\\)$", "$1");        //最小運算式計算    if(expression.matches(minExp)){      String result=calculate(expression);      return Double.parseDouble(result)>=0?result:"["+result+"]";    }    //計算不帶括弧的四則運算    if(expression.matches(noParentheses)){      Pattern patt=Pattern.compile(priorOperatorExp);      Matcher mat=patt.matcher(expression);      if(mat.find()){        String tempMinExp=mat.group();        expression=expression.replaceFirst(priorOperatorExp, parseExp(tempMinExp));      }else{        patt=Pattern.compile(operatorExp);        mat=patt.matcher(expression);                if(mat.find()){          String tempMinExp=mat.group();          expression=expression.replaceFirst(operatorExp, parseExp(tempMinExp));        }      }      return parseExp(expression);    }        //計算帶括弧的四則運算    Pattern patt=Pattern.compile(minParentheses);    Matcher mat=patt.matcher(expression);    if(mat.find()){      String tempMinExp=mat.group();      expression=expression.replaceFirst(minParentheses, parseExp(tempMinExp));    }    return parseExp(expression);  }  /**   * 計算最小單位四則運算運算式(兩個數字)   * @param exp   * @return   */  private static String calculate(String exp){    exp=exp.replaceAll("[\\[\\]]", "");    String number[]=exp.replaceFirst("(\\d)[\\+\\-\\*\\/]", "$1,").split(",");    BigDecimal number1=new BigDecimal(number[0]);    BigDecimal number2=new BigDecimal(number[1]);    BigDecimal result=null;        String operator=exp.replaceFirst("^.*\\d([\\+\\-\\*\\/]).+$", "$1");    if("+".equals(operator)){      result=number1.add(number2);    }else if("-".equals(operator)){      result=number1.subtract(number2);    }else if("*".equals(operator)){      result=number1.multiply(number2);    }else if("/".equals(operator)){      //第二個參數為精度,第三個為四色五入的模式      result=number1.divide(number2,5,BigDecimal.ROUND_CEILING);    }        return result!=null?result.toString():null;  }  }

代碼原本是一個部落格,原來代碼沒有注釋而且存在BUG,我稍微修稿了一哈添加了注釋。在這裡做個筆記,方便以後用

另為表示對原作者的敬意,附上原始代碼

/** * 四則運算運算式計算 * @author penli * */public class Arithmetic { public static void main(String args[]){ System.out.println(arithmetic("2.2+((3+4)*2-22)/2*3.2")); } public static double arithmetic(String exp){ String result = parseExp(exp).replaceAll("[\\[\\]]", ""); return Double.parseDouble(result); } /** * 解析計算四則運算運算式,例:2+((3+4)*2-22)/2*3 * @param expression * @return */ public static String parseExp(String expression){ //String numberReg="^((?!0)\\d+(\\.\\d+(?<!0))?)|(0\\.\\d+(?<!0))$"; expression=expression.replaceAll("\\s+", "").replaceAll("^\\((.+)\\)$", "$1"); String checkExp="\\d"; String minExp="^((\\d+(\\.\\d+)?)|(\\[\\-\\d+(\\.\\d+)?\\]))[\\+\\-\\*\\/]((\\d+(\\.\\d+)?)|(\\[\\-\\d+(\\.\\d+)?\\]))$"; //最小運算式計算 if(expression.matches(minExp)){  String result=calculate(expression);    return Double.parseDouble(result)>=0?result:"["+result+"]"; } //計算不帶括弧的四則運算 String noParentheses="^[^\\(\\)]+$"; String priorOperatorExp="(((\\d+(\\.\\d+)?)|(\\[\\-\\d+(\\.\\d+)?\\]))[\\*\\/]((\\d+(\\.\\d+)?)|(\\[\\-\\d+(\\.\\d+)?\\])))"; String operatorExp="(((\\d+(\\.\\d+)?)|(\\[\\-\\d+(\\.\\d+)?\\]))[\\+\\-]((\\d+(\\.\\d+)?)|(\\[\\-\\d+(\\.\\d+)?\\])))"; if(expression.matches(noParentheses)){  Pattern patt=Pattern.compile(priorOperatorExp);  Matcher mat=patt.matcher(expression);  if(mat.find()){  String tempMinExp=mat.group();  expression=expression.replaceFirst(priorOperatorExp, parseExp(tempMinExp));  }else{  patt=Pattern.compile(operatorExp);  mat=patt.matcher(expression);    if(mat.find()){   String tempMinExp=mat.group();   expression=expression.replaceFirst(operatorExp, parseExp(tempMinExp));  }  }  return parseExp(expression); } //計算帶括弧的四則運算 String minParentheses="\\([^\\(\\)]+\\)"; Pattern patt=Pattern.compile(minParentheses); Matcher mat=patt.matcher(expression); if(mat.find()){  String tempMinExp=mat.group();  expression=expression.replaceFirst(minParentheses, parseExp(tempMinExp)); } return parseExp(expression); } /** * 計算最小單位四則運算運算式(兩個數字) * @param exp * @return */ public static String calculate(String exp){ exp=exp.replaceAll("[\\[\\]]", ""); String number[]=exp.replaceFirst("(\\d)[\\+\\-\\*\\/]", "$1,").split(","); BigDecimal number1=new BigDecimal(number[0]); BigDecimal number2=new BigDecimal(number[1]); BigDecimal result=null;  String operator=exp.replaceFirst("^.*\\d([\\+\\-\\*\\/]).+$", "$1"); if("+".equals(operator)){  result=number1.add(number2); }else if("-".equals(operator)){  result=number1.subtract(number2); }else if("*".equals(operator)){  result=number1.multiply(number2); }else if("/".equals(operator)){  result=number1.divide(number2); }  return result!=null?result.toString():null; }}

最後給大家分享一個網友的實現方法,個人感覺也很不錯

import java.util.Stack; /**   * 利用棧,進行四則運算的類   * 用兩個棧來實現算符優先,一個棧用來儲存需要計算的資料numStack,一個用來儲存計算優先符priStack   *   * 基本演算法實現思路為:用當前取得的運算子與priStack棧頂運算子比較優先順序:若高於,則因為會先運算,放入棧頂;   * 若等於,因為出現在後面,所以會後計算,所以棧頂元素出棧,取出運算元運算;   * 若小於,則同理,取出棧頂元素運算,將結果入運算元棧。各個優先順序'(' > '*' = '/' > '+' = '-' > ')'   *   */   public class Operate {     private Stack<Character> priStack = new Stack<Character>();// 操作符棧     private Stack<Integer> numStack = new Stack<Integer>();;// 運算元棧        /**     * 傳入需要解析的字串,返回計算結果(此處因為時間問題,省略合法性驗證)     * @param str 需要進行技術的運算式     * @return 計算結果     */     public int caculate(String str) {       // 1.判斷string當中有沒有非法字元       String temp;// 用來臨時存放讀取的字元       // 2.迴圈開始解析字串,當字串解析完,且符號棧為空白時,則計算完成       StringBuffer tempNum = new StringBuffer();// 用來臨時存放數字字串(當為多位元時)       StringBuffer string = new StringBuffer().append(str);// 用來儲存,提高效率          while (string.length() != 0) {         temp = string.substring(0, 1);         string.delete(0, 1);         // 判斷temp,當temp為操作符時         if (!isNum(temp)) {           // 1.此時的tempNum內即為需要操作的數,取出數,壓棧,並且清空tempNum           if (!"".equals(tempNum.toString())) {             // 當運算式的第一個符號為括弧             int num = Integer.parseInt(tempNum.toString());             numStack.push(num);           tempNum.delete(0, tempNum.length());           }           // 用當前取得的運算子與棧頂運算子比較優先順序:若高於,則因為會先運算,放入棧頂;若等於,因為出現在後面,所以會後計算,所以棧頂元素出棧,取出運算元運算;           // 若小於,則同理,取出棧頂元素運算,將結果入運算元棧。              // 判斷當前運算子與棧頂元素優先順序,取出元素,進行計算(因為優先順序可能小於棧頂元素,還小於第二個元素等等,需要用迴圈判斷)           while (!compare(temp.charAt(0)) && (!priStack.empty())) {            int a = (int) numStack.pop();// 第二個運算數             int b = (int) numStack.pop();// 第一個運算數             char ope = priStack.pop();             int result = 0;// 運算結果             switch (ope) {             // 如果是加號或者減號,則             case '+':               result = b + a;               // 將操作結果放入運算元棧               numStack.push(result);               break;             case '-':               result = b - a;               // 將操作結果放入運算元棧               numStack.push(result);               break;             case '*':               result = b * a;               // 將操作結果放入運算元棧               numStack.push(result);               break;             case '/':               result = b / a;// 將操作結果放入運算元棧               numStack.push(result);               break;             }              }           // 判斷當前運算子與棧頂元素優先順序, 如果高,或者低於平,計算完後,將當前操作符號,放入操作符棧           if (temp.charAt(0) != '#') {             priStack.push(new Character(temp.charAt(0)));             if (temp.charAt(0) == ')') {// 當棧頂為'(',而當前元素為')'時,則是括弧內以算完,去掉括弧               priStack.pop();               priStack.pop();             }           }         } else           // 當為非操作符時(數字)           tempNum = tempNum.append(temp);// 將讀到的這一位元接到以讀出的數後(當不是個位元的時候)       }       return numStack.pop();     }        /**     * 判斷傳入的字元是不是0-9的數字     *     * @param str     *      傳入的字串     * @return     */     private boolean isNum(String temp) {       return temp.matches("[0-9]");     }        /**     * 比較當前操作符與棧頂元素操作符優先順序,如果比棧頂元素優先順序高,則返回true,否則返回false     *     * @param str 需要進行比較的字元     * @return 比較結果 true代表比棧頂元素優先順序高,false代表比棧頂元素優先順序低     */     private boolean compare(char str) {       if (priStack.empty()) {         // 當為空白時,顯然 當前優先順序最低,返回高         return true;       }       char last = (char) priStack.lastElement();       // 如果棧頂為'('顯然,優先順序最低,')'不可能為棧頂。       if (last == '(') {         return true;       }       switch (str) {       case '#':         return false;// 結束符       case '(':         // '('優先順序最高,顯然返回true         return true;       case ')':         // ')'優先順序最低,         return false;       case '*': {         // '*/'優先順序只比'+-'高         if (last == '+' || last == '-')           return true;         else           return false;       }       case '/': {         if (last == '+' || last == '-')           return true;         else           return false;       }         // '+-'為最低,一直返回false       case '+':         return false;       case '-':         return false;       }       return true;     }        public static void main(String args[]) {       Operate operate = new Operate();       int t = operate.caculate("(3+4*(4*10-10/2)#");        System.out.println(t);     }      }   

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.