仿android計算器,實現了括號

efbb 9年前發布 | 2K 次閱讀 Java Android

 
package com.fire.utils;

import java.text.DecimalFormat; import java.text.NumberFormat; import java.util.ArrayList; import java.util.List; import java.util.StringTokenizer;

/**

  • 工具類
  • @author FireAnt / public class Tools {

    public static int i = 0;

    /**

    • 計算一個合法的表達式的值
    • @param exp
    • @return */ public static String cal(String exp) {

      // 特殊表達式的處理方式 if (exp.length() == 0) {

       return "";
      

      } else if (exp.length() == 1) {

       if (exp.equals(".")) {
      
           return "0";
       } else {
      
           return "";
       }
      

      } else if (exp.matches(".÷0.")) { // 0作為除數

       return "∞";
      

      } else if (exp.matches(".*[+-/×÷]")) {

       exp = exp.substring(0, exp.length() - 1);
       if (exp.equals(".")) {
           return "0";
       }   
      

      }

      // 如果表達式中有括號則遞歸計算 if (exp.contains("(")) {

       // 找出最后一個左括號
       int left = exp.lastIndexOf("(");
       // 找出第一個右括號
       int right = exp.indexOf(")");
       // 獲取第一個子表達式
       String subExp = exp.substring(left + 1, right);
       // 計算子表達式的結果
       String res = cal(subExp); 
       // 用計算出來的結果替換子表達式
       exp = exp.substring(0, left) + res + exp.substring(right + 1);
       // 遞歸計算新的表達式
       exp = cal(exp);
      

      }

      // 格式化表達式 String newExp = formatExp(exp); List<Character> opts = getOptions(newExp); List<Double> nums = getNums(newExp);

      // 先處理乘除 for (int i = 0; i < opts.size(); i++) {

       char opt = opts.get(i);
       if (opt == '÷' || opt == '×') {
      
           opts.remove(i);
           double d1 = nums.remove(i);
           double d2 = nums.remove(i);
           if (opt == '÷') {
      
               d1 = d1 / d2;
      
           } else {
      
               d1 = d1 * d2;
           }
           nums.add(i, d1);
           i--;
       }
      

      }

      while (!opts.isEmpty()) {

       char opt = opts.remove(0);
       double d1 = nums.remove(0);
       double d2 = nums.remove(0);
       if (opt == '+') {
           d1 = d1 + d2;
       } else {
           d1 = d1 - d2;
       }
       nums.add(0, d1);
      

      }

      return formatNum(nums.get(0)); }

      /**

    • 獲得一個表達式中所有的運算符
    • @param exp
    • @return */ private static List<Character> getOptions(String exp) {

      List<Character> opts = new ArrayList<Character>(); StringTokenizer st = new StringTokenizer(exp, "@.0123456789"); while (st.hasMoreTokens()) {

       opts.add(st.nextToken().charAt(0));
      

      } return opts; }

      /**

    • 獲得一個表達式中所有的數字
    • @param exp
    • @return */ private static List<Double> getNums(String exp) {

      List<Double> nums = new ArrayList<Double>(); StringTokenizer st = new StringTokenizer(exp, "+-×÷"); while (st.hasMoreTokens()) {

       String num = st.nextToken();
       if (num.contains("@")) {
      
           num = "-" + num.substring(1);
       }
       nums.add(Double.parseDouble(num));
      

      } return nums; }

      /**

    • 格式一個浮點數
    • @param num
    • @return */ public static String formatNum(double num) {

      DecimalFormat df = (DecimalFormat) NumberFormat.getInstance();

      df.applyLocalizedPattern("#0.##########"); if (num > 1000000000) {

       df.applyPattern("#0.#######E0");
      

      }

      return df.format(num); }

      /**

    • 格式化表達式
    • 1.替換操作(找出負號,并將其替換成@符號)
    • 2.避免非法表達式的出現 */ private static String formatExp(String exp) {

      // 如果表達式是以運算符結束的,則將最后一位運算符去除 if (exp.matches(".*[+-/×÷]")) {

      exp = exp.substring(0, exp.length() - 1);
      

      } String res = exp; if (exp.charAt(0) == '-') {

      res = "@" + res.substring(1);
      

      }

      for (int i = 1; i < res.length(); i++) {

      if (res.charAt(i) == '-' && (res.charAt(i - 1) == '÷' || res.charAt(i - 1) == '×')) {
      
          res = res.substring(0, i) + "@" + res.substring(i + 1);
      }
      

      } return res; }

      /**

    • 檢查表達式是否有括號,并且檢查是否符合
    • @param exp
    • @return */ public static boolean checkExp(String exp) {

      boolean res = true;

      int index = exp.indexOf("("); if (index != -1) {

       int leftN = 0;
       for (int i = index; i < exp.length(); i++) {
      
           if (exp.charAt(i) == '(') {
               leftN++;
           }
           else if (exp.charAt(i) == ')') {
               leftN--;
               if (leftN == -1) {
                   res = false;
                   break;
               }
           }
       }
       if (leftN > 0) {
      
           res = false;
       }
      

      }

      return res; } }

</pre>

 本文由用戶 efbb 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!