Java愛好者

          一個堅定的Java愛好者,歡迎和我討論
          隨筆 - 7, 文章 - 8, 評論 - 6, 引用 - 0

          導航

          <2006年6月>
          28293031123
          45678910
          11121314151617
          18192021222324
          2526272829301
          2345678

          公告

          Spring、Hibernate、Shark、Struts、XML歡迎交換使用心得

          常用鏈接

          留言簿(1)

          文章分類

          搜索

          •  

          最新評論

          閱讀排行榜

          評論排行榜

          一個計算表達式的類,供參考

          package cn.com.worksoft.util.expression;

          import java.util.Arrays;

          import cn.com.worksoft.util.log.LogFactory;
          import cn.com.worksoft.util.log.Logger;

          /**
          *
          * @author XING
          *
          * Create time 2004-12-2 16:52:48
          *
          * 本類的運算邏輯是 分為以下幾個步驟:
          * 1、格式化所輸入的算式(去掉所有空格,+-符號前面如果沒有數字就補0,×/符號前面如果沒有數字就補1,^~符號后面如果沒有數字就補2,其它如果出現前后缺少的情況就報錯)
          * 2、獲得的算式串,如A; 3、獲取所有運算符號,尋找第一個需要運算的符號,基本規則是,找到最里層的(),然后在其內部找,^~ > /* > +-
          * ,同類型的就從做至右運算; 4、獲取該運算符號的兩端變量,進行運算得出結果,將結果回填回去; 5、取得了新的運算串,存入A;
          * 6、重復2直到A中沒有運算符號為止; 7、得到結果。
          *
          * 更改所生成類型注釋的模板為 窗口 > 首選項 > Java > 代碼生成 > 代碼和注釋
          */
          public final class TExpression {
          public final static String ADD = "\\\\+";

          public final static String DECREASE = "\\\\-";

          public final static String[] DefaultVars = new String[]
          {
          "+",
          "-",
          "*",
          "/",
          "^",
          "~", };

          public final static String DIVIDE = "/";

          public final static String FU = "GXFU";

          public final static String LBRACKET = "\\\\(";

          public final static String MULTIPLY = "\\\\*";

          public final static String PERCENT = "%";

          public final static String POWER = "\\\\^";

          public final static String RBRACKET = "\\\\)";

          public final static String SQRT = "~";

          private final static Logger gLogger = LogFactory.defaultFacotry()
          .createNewLogger();

          /**
          * 將arg0數組,完全加在arg1的后面。
          *
          * @param arg0
          * @param arg1
          * @return
          */
          private static int[] addAll(int[] arg0, int[] arg1) {
          int[] arg = new int[arg0.length + arg1.length];
          for (int i = 0; i < arg0.length + arg1.length; i++) {
          if (i < arg0.length)
          arg[i] = arg0[i];
          else
          arg[i] = arg1[i - arg0.length];
          }
          return arg;
          }

          /**
          * 檢查括號是否正確使用。
          *
          * @param arg
          * @return
          */
          private static boolean CheckBracket(String arg) {
          boolean bln = true;
          if (SubStrCount(arg, "(") != SubStrCount(arg, ")")) {
          bln = false;
          }
          if (bln) {
          int[] lbracket = indexOf(arg, "(");
          int[] rbracket = indexOf(arg, ")");
          int length = lbracket.length;
          // new ErrPrintArray(System.err).printArray(lbracket);
          for (int i = 0; i < length; i++) {
          bln &= lbracket[i] < rbracket[i];
          }
          }

          return bln;
          }

          /**
          * 檢查表達式,并返回最終合格得表達式結果,如果無法返回合格得結果,將拋出異常。
          *
          * @param arg
          * @throws Exception
          * @return
          */
          private static String CheckTExpression(String arg) throws Exception {
          // / 檢查符號前后是否存在空缺。
          arg = Trim(arg);
          // / 將%修改成/100的運算符。
          arg = arg.replaceAll(TExpression.PERCENT, "/100");
          if (!CheckBracket(arg))
          throw new Exception("括號沒有匹配或者使用不當,請檢查!");
          // / 在)(之間增加*符號。
          arg = TrimBracket(arg);
          // / 如果-號開頭,那么就在前面增加一個FU
          if (arg.substring(0, 1).equals("-")) {
          arg = TExpression.FU + arg.substring(1, arg.length());
          }
          // / 如果+號開頭,那么就去掉+號
          if (arg.substring(0, 1).equals("-")) {
          arg = arg.substring(1, arg.length());
          }
          // / 如果*/號開頭,那么前面加一個1
          else if (arg.substring(0, 1).equals("*")
          || arg.substring(0, 1).equals("/")) {
          arg = arg.substring(1, arg.length());
          } else if (arg.substring(0, 1).equals("^")) {
          throw new Exception("~符號不能用在公式開頭的位置!");
          } else if (arg.substring(0, 1).equals("^")) {
          throw new Exception("∧符號不能用在公式開頭的位置!");
          }
          return arg;
          }

          public static String Do(String expression, boolean showProcess)
          throws Exception {
          String testStr = expression;
          /**
          * 檢查字符串。
          */
          String aa = null;
          try {
          aa = CheckTExpression(testStr);
          } catch (Exception e) {
          gLogger.error(e.getMessage(), e);
          e.printStackTrace();
          }
          try {
          String[] bb = TExpression.getVars(aa, DefaultVars);
          int i = 0;
          // 如果操作完的結果跟操作前相同,說明不需要繼續運算
          // 增加i,避免死循環。
          while (bb.length != 0 && i < 10000) {
          aa = doOperate(aa);
          if (showProcess) {
          gLogger.info(aa);
          }
          bb = TExpression.getVars(aa, DefaultVars);
          if (!isNaN(TrimAllBracket(aa))) {
          aa = TrimAllBracket(aa);
          break;
          }
          i++;
          }
          aa = TrimAllBracket(aa);
          } catch (Exception e) {
          gLogger.error(e.getMessage(), e);
          e.printStackTrace();
          }
          return aa;
          }

          /**
          * 對整個公式進行單步運算。
          *
          * @param arg
          * @return
          * @throws Exception
          */
          private static String doOperate(String arg) throws Exception {
          String leftRLT = "";
          String rightRLT = "";
          String rlt = arg;
          int[] rkfs = TExpression.indexOf(rlt, new String[]
          { ")", });
          int[] lkfs = TExpression.indexOf(rlt, new String[]
          { "(", });
          // 找到第一個)符號。
          // // 如果一個都沒有找到,那么直接對整個公式進行操作。
          if (rkfs.length == 0) {
          leftRLT = "";
          rightRLT = "";
          rlt = arg;
          }
          // // 否則,取()中間的內容,進行操作。
          else {
          int firstRkf = rkfs[0];
          // System.out.println(arg.substring(firstRkf - 1, firstRkf + 2));
          // 找到與第一個)符號對應的(
          int containsLkf = lkfs[0];
          for (int i = 1; i < lkfs.length; i++) {
          if (lkfs[i] > firstRkf)
          break;
          else
          containsLkf = lkfs[i];
          }
          // System.out.println(arg.substring(containsLkf - 1, containsLkf +
          // 2));
          // 取得中間的串,并取得兩端的串。
          leftRLT = rlt.substring(0, containsLkf);
          rightRLT = rlt.substring(firstRkf + 1, rlt.length());
          rlt = rlt.substring(containsLkf + 1, firstRkf);
          }
          // System.out.println(rlt);
          // 重新檢查語法
          rlt = CheckTExpression(rlt);

          String[] vars = getVars(rlt, DefaultVars);
          String[] ops = getOperates(rlt, DefaultVars);
          if (1 == 2) {
          return null;
          }
          // 找到^~的運算
          // // 如果存在^符號而且不存在~,或者存在^符號而且存在~符號并且^符號在~符號之前,那么就先運算^符號。
          else if ((rlt.indexOf("^") != -1 && rlt.indexOf("~") == -1)
          || (rlt.indexOf("^") != -1 && rlt.indexOf("~") != -1 && rlt
          .indexOf("^") < rlt.indexOf("~"))) {
          int index = indexOf(ops, "^");
          String op = TExpression.POWER;
          rlt = doOperate1(rlt, vars[index], vars[index + 1], op);
          rlt = "(" + rlt + ")";
          }
          // // 如果存在~符號而且不存在^,或者存在~符號而且存在^符號并且~符號在^符號之前,那么就先運算~符號。
          else if ((rlt.indexOf("~") != -1 && rlt.indexOf("^") == -1)
          || (rlt.indexOf("~") != -1 && rlt.indexOf("^") != -1 && rlt
          .indexOf("~") < rlt.indexOf("^"))) {
          int index = indexOf(ops, "~");
          if (vars[index + 1].equals("0"))
          throw new Exception("【嚴重錯誤】:開方數不能為零");
          String op = TExpression.SQRT;
          rlt = doOperate1(rlt, vars[index], vars[index + 1], op);
          rlt = "(" + rlt + ")";
          }
          // 如果沒有找到,那么找*/的運算
          else if ((rlt.indexOf("*") != -1 && rlt.indexOf("/") == -1)
          || (rlt.indexOf("*") != -1 && rlt.indexOf("/") != -1 && rlt
          .indexOf("*") < rlt.indexOf("/"))) {
          int index = indexOf(ops, "*");
          String op = TExpression.MULTIPLY;
          rlt = doOperate1(rlt, vars[index], vars[index + 1], op);
          rlt = "(" + rlt + ")";
          }
          // // 如果存在~符號而且不存在^,或者存在~符號而且存在^符號并且~符號在^符號之前,那么就先運算~符號。
          else if ((rlt.indexOf("/") != -1 && rlt.indexOf("*") == -1)
          || (rlt.indexOf("/") != -1 && rlt.indexOf("*") != -1 && rlt
          .indexOf("/") < rlt.indexOf("*"))) {
          int index = indexOf(ops, "/");
          if (vars[index + 1].equals("0"))
          throw new Exception("【嚴重錯誤】:除數為零");
          String op = TExpression.DIVIDE;
          rlt = doOperate1(rlt, vars[index], vars[index + 1], op);
          rlt = "(" + rlt + ")";
          }
          // 如果沒有找到,那么找+-運算
          else if ((rlt.indexOf("+") != -1 && rlt.indexOf("-") == -1)
          || (rlt.indexOf("+") != -1 && rlt.indexOf("-") != -1 && rlt
          .indexOf("+") < rlt.indexOf("-"))) {
          int index = indexOf(ops, "+");
          String op = TExpression.ADD;
          rlt = doOperate1(rlt, vars[index], vars[index + 1], op);
          rlt = "(" + rlt + ")";
          }
          // // 如果存在~符號而且不存在^,或者存在~符號而且存在^符號并且~符號在^符號之前,那么就先運算~符號。
          else if ((rlt.indexOf("-") != -1 && rlt.indexOf("+") == -1)
          || (rlt.indexOf("-") != -1 && rlt.indexOf("+") != -1 && rlt
          .indexOf("-") < rlt.indexOf("+"))) {
          int index = indexOf(ops, "-");
          String op = TExpression.DECREASE;
          rlt = doOperate1(rlt, vars[index], vars[index + 1], op);
          rlt = "(" + rlt + ")";
          }
          // // 如果什么符號都沒有找到,說明該串是個單變量的串,直接去掉兩端的括號,返回。
          else {
          rlt = TrimAllBracket(rlt);
          }
          // 把運算結果替換到適當的位置,然后返回。
          return leftRLT + rlt + rightRLT;
          }

          /**
          * 執行某個運算操作。
          *
          * @param vars
          * @param ops
          * @param op
          *????????????如:"\\\\*"
          * @return
          * @throws Exception
          */
          private static String doOperate1(String rlt, String var1, String var2,
          String op) throws Exception {
          String tmp = var1 + op + var2;
          if (var1.indexOf(TExpression.FU) != -1) {
          var1 = var1.replaceAll(TExpression.FU, "-");
          }
          if (!isNaN(var1) && !isNaN(var2)) {
          // System.out.println(tmp);
          rlt = rlt.replaceFirst(tmp, "" + operate(var1, var2, op));
          }
          rlt = "(" + rlt + ")";
          return rlt;
          }

          /**
          * 返回int數組中最小的一個。 假設數組中不存在相等的情況。
          *
          * @param arg
          * @return
          */
          private static int getMin(int[] arg, int fromIndex) throws Exception {
          int i = arg[fromIndex];
          for (int k = fromIndex + 1; k < arg.length; k++) {
          if (arg[k] < i) {
          i = arg[k];
          } else if (arg[k] == i && arg[k] != Integer.MAX_value)
          throw new Exception("數組中存在相等的值,無法進行取最小值的運算。");
          }
          return i;
          }

          /**
          * 返回arg1中在arg2數組中存在的所有變量的順序組合。 如 (5*4+3) 返回 {*,+} ;
          *
          * @param arg1
          * @param arg2
          * @return
          * @throws Exception
          */
          private static String[] getOperates(String arg1, String[] arg2)
          throws Exception {
          int[] indexs = indexOf(arg1, arg2);
          String[] ops = new String[indexs.length];
          for (int i = 0; i < indexs.length; i++) {
          ops[i] = arg1.substring(indexs[i], indexs[i] + 1);
          }
          return ops;
          }

          /**
          * 返回arg1中在arg2數組中存在的所有變量兩端的變量的順序組合。 如 (5*4+3) 返回 {5,4,3} ;
          *
          * @param arg1
          * @param arg2
          * @return
          * @throws Exception
          */
          private static String[] getVars(String arg1, String[] arg2)
          throws Exception {
          // 去掉所有括號。
          arg1 = arg1.replaceAll(TExpression.LBRACKET, "");
          arg1 = arg1.replaceAll(TExpression.RBRACKET, "");

          int[] indexs = indexOf(arg1, arg2);
          // 如果沒有運算符,那么返回本身。
          if (indexs.length == 0)
          return new String[]
          { arg1 };
          String[] vars = new String[indexs.length + 1];
          for (int i = 0; i < indexs.length + 1; i++) {
          if (i == 0)
          vars[i] = arg1.substring(0, indexs[i]);
          else if (i == indexs.length)
          vars[i] = arg1.substring(indexs[i - 1] + 1, arg1.length());
          else
          vars[i] = arg1.substring(indexs[i - 1] + 1, indexs[i]);
          }
          return vars;
          }

          /**
          * 取得arg0中arg1的所有索引的值。
          *
          * @param arg0
          * @param arg1
          * @return
          */
          private static int[] indexOf(String arg0, String arg1) {
          int i = 0;
          int j = 0;
          int[] intArr = new int[SubStrCount(arg0, arg1)];
          while (arg0.indexOf(arg1, i) != -1) {
          intArr[j] = arg0.indexOf(arg1, i);
          i = intArr[j] + 1;
          j++;
          }
          return intArr;
          }

          /**
          * 取得arg0中arg1[]任意一個的所有索引的值。
          *
          * @param arg0
          * @param arg1
          * @return
          */
          private static int[] indexOf(String arg0, String[] arg1) throws Exception {
          int j = 0;
          // 取得arg1中所有成員最近的位置。
          int[] targets = new int[0];
          for (int k = 0; k < arg1.length; k++) {
          targets = addAll(targets, indexOf(arg0, arg1[k]));
          }
          Arrays.sort(targets);
          int[] intArr = new int[targets.length];
          while (j < intArr.length) {
          // 取得最近的一個成員的位置。
          int target = getMin(targets, j);
          intArr[j] = target;
          j++;
          }
          return intArr;
          }

          /**
          * 返回字串數組中,相關值對應的索引。
          *
          * @param arg1
          * @param arg2
          * @return
          */
          private static int indexOf(String[] arg1, String arg2) {
          for (int i = 0; i < arg1.length; i++) {
          if (arg2.equals(arg1[i]))
          return i;
          }
          return -1;
          }

          /**
          * 判斷是否為數字。
          *
          * @param arg
          * @return
          */
          private static boolean isNaN(String arg) {
          if (arg == null || arg.length() == 0)
          return true;
          try {
          Double.parseDouble(arg);
          } catch (NumberFormatException e) {
          return true;
          }
          return false;
          }

          public static void main(String[] args) {
          String testStr = "((-1-2%*3^(4)~2/1)(7+8)-9)()";
          testStr = "150*(200-600/40)*12+14*3-55+76+23/3+5+5";
          // testStr = "150*(200-600/40)*12+14*3-55+76+23/3+5+5/0";
          // System.err.println(testStr);

          // System.out.println("gdasfds");
          // System.out.println("gdasfds".replaceAll("k", ""));
          // System.out.println(SubStrCount(testStr, "~"));
          // System.out.println("gdass".indexOf("k"));
          // new
          // ErrPrintArray(System.err).printArray(TExpression.indexOf("fagaxa",
          // "a"));
          /**
          * 檢驗括號是否正確。
          */
          // boolean kk = CheckBracket(testStr);
          // System.err.println(kk);
          /**
          * 獲得字符串中所有變量的順序組合。
          */
          try {
          // new ErrPrintArray(System.err).printArray(TExpression.getVars(aa,
          // new String[] { "+", "-", "*", "/", "^", "~", }));
          } catch (Exception e) {
          e.printStackTrace();
          }
          /**
          * 正式測試功能。
          */
          try {
          testStr = Do(testStr, true);
          } catch (Exception e) {
          e.printStackTrace();
          }
          System.err.println(testStr);
          }

          /**
          * 直接運算得到結果。
          *
          * @param arg1
          * @param arg2
          * @param op
          * @return
          * @throws Exception
          */
          private static double operate(String arg1, String arg2, String op)
          throws Exception {
          double a1 = Double.parseDouble(arg1);
          double a2 = Double.parseDouble(arg2);
          if (op.equals(TExpression.ADD)) {
          return a1 + a2;
          } else if (op.equals(TExpression.DECREASE)) {
          return a1 - a2;
          } else if (op.equals(TExpression.MULTIPLY)) {
          return a1 * a2;
          } else if (op.equals(TExpression.DIVIDE)) {
          return a1 / a2;
          } else if (op.equals(TExpression.SQRT)) {
          return Math.pow(a1, 1 / a2);
          } else if (op.equals(TExpression.POWER)) {
          return Math.pow(a1, a2);
          }
          return 0d;
          }

          /**
          * 返回arg0中包含的arg1的個數。
          *
          * @param arg0
          * @param arg1
          * @return
          */
          private static int SubStrCount(String arg0, String arg1) {
          int i = 0;
          arg0 = Trim(arg0);
          i = arg0.length();
          arg1 = arg1.replaceAll("\\\\+", "\\\\" + ADD);
          arg1 = arg1.replaceAll("\\\\-", "\\\\" + TExpression.DECREASE);
          arg1 = arg1.replaceAll("\\\\*", "\\\\" + TExpression.MULTIPLY);
          arg1 = arg1.replaceAll("\\\\^", "\\\\" + TExpression.POWER);
          arg1 = arg1.replaceAll("\\\\(", "\\\\" + TExpression.LBRACKET);
          arg1 = arg1.replaceAll("\\\\)", "\\\\" + TExpression.RBRACKET);
          i = i - arg0.replaceAll(arg1, "").length();
          return i;
          }

          /**
          * 去除所有包含的空格。
          *
          * @param arg
          * @return
          */
          private static String Trim(String arg) {
          String rlt = "";
          rlt = arg.replaceAll(" ", "");
          return rlt;
          }

          /**
          * 去掉字串中的所有),(符號。
          *
          * @param arg
          * @return
          */
          private static String TrimAllBracket(String arg) {
          String rlt = arg;
          rlt = rlt.replaceAll("\\\\(", "");
          rlt = rlt.replaceAll("\\\\)", "");
          return rlt;
          }

          /**
          * 去掉多余的()符號; 在)(之間增加*符號;
          *
          * @param arg
          * @return
          */
          private static String TrimBracket(String arg) {
          String rlt = arg;
          rlt = rlt.replaceAll("\\\\(\\\\)", "");
          rlt = rlt.replaceAll("\\\\)\\\\(", "\\\\)\\\\*\\\\(");
          return rlt;
          }
          }

          posted on 2006-06-30 14:30 JStar 閱讀(1428) 評論(0)  編輯  收藏


          只有注冊用戶登錄后才能發表評論。


          網站導航:
           
          主站蜘蛛池模板: 大连市| 固始县| 慈利县| 惠来县| 古蔺县| 大丰市| 西畴县| 北川| 泗水县| 平果县| 银川市| 奇台县| 盐城市| 根河市| 福安市| 乌拉特后旗| 仙桃市| 揭阳市| 垦利县| 临西县| 阳曲县| 灵台县| 湟源县| 上饶市| 宁波市| 中西区| 永平县| 县级市| 洱源县| 灵丘县| 常德市| 丰宁| 于都县| 涪陵区| 鹤庆县| 千阳县| 屏东市| 大同市| 根河市| 阿鲁科尔沁旗| 张家界市|