Yesterday, I was in a hurry. I also estimate that there is a bug. I explain it here. I don't want to use PARSEINT. I don't want to use floating point calculations to sacrifice performance! I have time I added.
Package treeroot.util.parser;
Class Operation {Private Int Priority; PriVate Operation (Int Priority) {this.priority = priority;
Public int getPriority () {return this.priority;
public static Operation PLUS = new Operation (1); public static Operation MINUS = new Operation (1); public static Operation MULTIPLY = new Operation (2); public static Operation DIVIDE = new Operation (2); public static Operation MOD = new Operation (2);} package treeroot.util.parser;
Class bracket {private bracket () {} public static bracket left = new bracket (); public static bracket right = new bracket ();} package treeroot.util.parser;
Import java.util. *; class stack {private list data = new arraylist (); private int size = 0; public boolean Empty () {returnize == 0;} public void push (Object O) {data.add ( o); Size ;} public object pop () {if (size> 0) {Return Data.Remove (- size);} return null;} public object peek () {if (size> 0) Return Data.Get (SIZE-1); return null;}} package treeroot.util.parser;
Class compute {
Static Int Compute (int N1, int N2, operation op) {
IF (OP == Operation.plus) {RETURN N1 N2;} else if (op == Operation.minus) {RETURN N1 - N2;} else if (op == Operation.diVide) {Return N1 / N2;} Else if (OP == Operation.MultiPly) {return n1 * n2;} else if (op == OPERATION.MOD) {RETURN N1% N2;} else {throw new unsupportedOperationException ();}}}}}} static double compute (double N1 , Double N2, Operation OP) {if (OP == Operation.plus) {RETURN N1 N2;} else if (OP == Operation.minus) {RETURN N1 - N2;} else if (op == Operation.diVide ) {RETURN N1 / N2;} else if (op == OPERATION.MULTIPLY) {RETURN N1 * N2;} else if (op == OPERATION.MOD) {RETURN N1% N2;} else {throw new unsupportedOperationException (); }}} // The following is the core code package treeroot.util.Parser; / ** * Support , -, *, /,%, (,), - (siGN), Dot (.) For Double * Int Double * / import java.util.list; import java.util.ArrayList; import java.text.parsexcep TI;
Public class expressionParser {private expressionParser ()} private static char [] Validcharsforint = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', ' ', '-', '*', '/', '%', '(', ')'}; private static char [] validcharsfordouble = {'0', ' 1 ',' 2 ',' 3 ',' 4 ',' 5 ',' 6 ',' 7 ',' 8 ',' 9 ',' ',' - ',' * ',' / ' , '%', '(') ','. '}; // check the valid char of the expression for the int compute private static boolean validcharforint (int i = 0; i // (private final static int LEFT_BRACKET = 0x100; //) private final static int RIGHT_BRACKET = 0x1000; // - private final static int SIGN = 0x10000; // for the double private final static int DOT = 0x100000; private static. int NULL_AFTER = NUMBER LEFT_BRACKET SIGN; private static int NUMBER_AFTER = NUMBER OPERATION RIGHT_BRACKET DOT; private static int OPERATION_AFTER = NUMBER LEFT_BRACKET; private static int LEFT_BRACKET_AFTER = NUMBER LEFT_BRACKET SIGN; private static int RIGHT_BRACKET_AFTER = OPERATION RIGHT_BRACKET ; private static int SIGN_AFTER = NUMBER LEFT_BRACKET; private static int DOT_AFTER = NUMBER; // for the convinent private static int [] TYPE = {NULL, NUMBER, OPERATION, LEFT_BRACKET, RIGHT_BRACKET, SIGN, DOT}; private static int [] EXPECT_AFTER = {NULL_AFTER, NUMBER_AFTER, OPERATION_AFTER, LEFT_BRACKET_AFTER, RIGHT_BRACKET_AFTER, SIGN_AFTER, DOT_AFTER}; private static boolean isEndType (int type) {return (type == NUMBER) || (type == RIGHT_BRACKET);} private static int getVal Idafter (int type) {for (INT i = 0; i } {Sb.append ("SIGN [ -],");} if (("(" ("Dot [.],");} SB. setLength (sb.length () - 1); return sb.toString ();} private static boolean checkExpect (int type, int next) {int expect = getValidAfter (type); return (next & expect)> 0;} private static void checkExpect (int type, int next, int index) throws ParseException {if {throw new ParseException (expectString (type) "expected at index" index, index) (checkExpect (type, next)!);}} public static double parseDouble (String expression) throws ParseException {if ((expression == null) |. (expression = expression.trim ()) equals ( "")) {throw new NullPointerException ( "! expression can not be null or blank") } Stack stack = new stack (); int CURTYPE = NULL; Boolean isnegative = false; int = 0; stringbuffer sb = new stringbuffer (); for (int i = 0; i } // sIGN Must After (or at the beginning); if (c == '-') isnegative = true; else isnegative = false;} Break; Case '*': Case '/': CASE '%': Checkexpect (curtype, Operation, i); if (c == '*') Push = Operation.Multiply; Else IF (c == '/') push = Operation.divide; else push = Operation.Mod ; curType = OPERATION; break; case '(': checkExpect (curType, LEFT_BRACKET, i); push = Bracket.LEFT; curType = LEFT_BRACKET; leftBrackets ; break; case ')': checkExpect (curType, RIGHT_BRACKET, i); push = Bracket.RIGHT; curType = RIGHT_BRACKET; leftBrackets--; if (leftBrackets <0) throw new IllegalArgumentException ( "unmatched right bracket at inidex" i); break; case '.': checkExpect (curType, DOT, i); Dot ; if (dot> 1) thro W New ILLEGALARGUMENTEXCEPTION ("Redundant Dot AT INDEX" I); Sb.Append (c); CURTYPE = Dot; Break; default: // must be number checkeexpect (curtype, number, i); sb.append (c); CURTYPE = Number;} // if it is a negative sign the push number -1 and * if (curtype == sign) && (isnegative)) {stack.push (new double (-1)); stack.push ( Operation.multiply;} // read a number if ((CURTYPE! = NUMBER) & & (CURTYPE! = DOT) && (sb.Length ()> 0)) {stack.push (new double (sb.parstring ())))); DOT = 0; sb.setlength (0); } // if not number and sign shop be pushed if (push! = Null) stack.push (push); if (CURTYPE == Operation) || (CURTYPE == Right_Bracket) {popdoublestack (stack);}} if (leftBrackets> 0) throw new IllegalArgumentException ( "unmatched brackets!"); if throw new IllegalArgumentException ( "invalid end char") (isEndType (curType)!); if ((curType == NUMBER) && (sb.length ( )> 0)) {stack.push (new double (sb.parstring ())))))); sb.setlength (0);} Double result = (Double) stack.pop ()). DoubleValue WHILE (! Stack.empty ()) {Operation OP = (Operation) stack.pop (); double number = (double) stack.pop (); result = compute.compute (Num.doubleValue (), ResUT, OP);} Return Result; e | not || Just for the simplity // do you know why? if (expression == null) | (Expression = expression.trim ()). Equals (")) {throw new nullpointerException (" Expression CAN " T be null or blank! ");} // Remember the priority so as to save the pop stack Times // int prepriority = 0; // int curpriority = 0; stack stack = new stack (); int CURTYPE = NULL; Boolean isnegative = false; int leftbrackets = 0; stringbuffer sb = new stringbuffer (); for (int i = 0; i Expression.Charat (i); // ignore blank while (c == ') {i ; c = expression.Charat (i);} // check valid char checkvalidcharforint (c, i); switch (c) {cas ' ': Case '-': Checkexpect (CURTYPE, OPERATION SIGN, I); // the Operation Must After Number OR) {CURTYPE = Operation ; If (c == ' ') push = Operation.plus; Else Push = Operation.minus;} // signing. Else {CURTYPE = Sign; if (c == '-') Isnegative = true; else isnegative = false;} break; case '*': Case '/': case '%': checkexpect (curtype, Operation, i); if (c == '*') push = Operation.Multiply ELSE IF (c == '/') push = Operation.divide; Else Push = Operation.mod; CURTYPE = Operation; Break; Case '(': checkexpect (CUR Type, LEFT_BRACKET, i); push = Bracket.LEFT; curType = LEFT_BRACKET; leftBrackets ; break; case ')': checkExpect (curType, RIGHT_BRACKET, i); push = Bracket.RIGHT; curType = RIGHT_BRACKET; leftBrackets--; if (Leftbrackets <0) Throw New IllegalargumentException ("Unmatched Right Bracket Atlyx" i); Break; Default: // Must Be Number Checkeexpect (Curtype, Number, i); Sb.append (c); curtype = number;} // if it is a negative sign the push number -1 and * if (curtype == sign) && (isnegative)) {stack.push (new integer (-1 ))); Stack.push (Operation.Multiply);} // read a number if ((curtype! = Number) && (sb.Length ()> 0)) {stack.push (new integer (integer.Parseint) .tostring ()))); sb.setLength (0);} // if not number and sign shop be pushed if (push! = null) stack.push (push); if ((CURTYPE == Operation) || (curType == RIGHT_BRACKET)) {popIntStack (stack);}} if (leftBrackets> 0) throw new IllegalArgumentException ( "unmatched brackets!");! if (isEndType (curType)) throw new IllegalArgumentException ( "invalid end char") ; If (CURTYPE == Number) && (sb.Length ()> 0)) {stack.push (new integer (sb.parstring ())))); sb.setlength (0);} int Result = ((Integer) stack.pop ()). INTVALUE (); while (! stack {Operation OP = (Operation) stack.pop (); Integer Num = (Integer) stack.pop (); result = compute.compute (Num.intValue (), Result, OP);} Return Result } Private static void popintstack (stack s) {object obj = s.pop (); // if it is) THEN POP IF (Obj == bracket.right) {// must be number, Becaurse The Stack Can Have No NO More Than 1 Right Brackets Integer i_1 = (Integer) s.POP (); Object OP_1 = S.POP (); if (OP_1 == Bracket.left) {// push back and return; s.push (i_1); Return; } // Op Must Be Operation Here // Next Must Be Number Integer i_2 = (Integer) S.POP (); // compute int result = compute.compute (i_2.intvalue (), i_1.intValue (), (Operation ) OP_1); s.push (new integer (result)); s.push (bracket.right); // recruitive; popintstack (s);} // Operation , -, *, /,% else if (Obj InstanceOf Operation) {// Must Be Number Operation OP_1 = (OPERATION) OBJ; Integer i_1 = (Integer) S.POP (); // if IT IS EMPTY IF (S.empty ()) {S.PUSH (i_1) ; S.push (op_1); return;} Object op_2 = s.POP (); // can't compute if it is left bracket or the pre has the Lower Priority IF ((op_2 == bracket.left) || ((OPERATION) OP_2) .GETPRIORITY ()