| 注册
请输入搜索内容

热门搜索

Java Linux MySQL PHP JavaScript Hibernate jQuery Nginx
g2b4
10年前发布

支持括号的仿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;      }  }