Advertisement
Guest User

Expression

a guest
Feb 20th, 2020
188
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Java 26.11 KB | None | 0 0
  1. import java.util.regex.Matcher;
  2. import java.util.regex.Pattern;
  3. /**
  4.  * Name: Trevor Brown
  5.  * Expression Project 2.0
  6.  */
  7. //Note: Currently all methods are made static to easily test their functionality in main.
  8. public class Expression {
  9.  
  10.     private String ex;
  11.     public Expression(String ex)
  12.     {
  13.         //Trim whitespace from string.
  14.         ex = ex.replaceAll("\\s", "");
  15.         if (checkSyntax(ex) == true)
  16.             this.ex = ex;
  17.         else
  18.             throw new IllegalArgumentException("Improper syntax used!");
  19.     }
  20.     public String getEx()
  21.     {
  22.         return ex;
  23.     }
  24.  
  25.  
  26.     /**
  27.      * @param e an expression in the form of a string.
  28.      * @return True if the expression has proper syntax, and false if not.
  29.      */
  30.     public static boolean checkSyntax(String e)
  31.     {
  32.  
  33.         //ACCEPTED TOKENS 0-9, (,),*,/,^,+,-,.
  34.         //Use regex for check if anything other than these tokens are present.
  35.         //I promise this is all of the criteria for proper syntax. You can't evaluate an expression that does not follow
  36.         //these rules.
  37.         Pattern p = Pattern.compile("[^\\-*\\/\\(\\)^\\+\\. 0-9]|--|[\\-*\\/^\\+.][\\-*\\/^\\+\\.]+|[(][*\\/^\\+\\.]|[\\-*\\/^\\+\\.][)]|[(][)]|[0-9][(]|[)][0-9]");
  38.         Matcher m = p.matcher(e);
  39.         if(m.find() == true)
  40.             return false;
  41.  
  42.         //count parenthesis.
  43.         int pCount = 0;
  44.         for(int i = 0; i < e.length(); i++)
  45.         {
  46.             if(e.charAt(i) == '(')
  47.                 pCount++;
  48.             if(e.charAt(i) == ')')
  49.                 pCount--;
  50.  
  51.             if (pCount < 0)
  52.                 return false;
  53.         }
  54.         if (pCount != 0)
  55.             return false;
  56.         return true;
  57.     }
  58.  
  59.     /*
  60.     First and most important subroutine is one that evaluates a single operation.
  61.     The function will have three parameters. two doubles and an operator character.
  62.      */
  63.  
  64.     /**
  65.      *
  66.      * @param d1 the first double
  67.      * @param operator the operation to perform on the two doubles
  68.      * @param d2 the second double
  69.      *
  70.      *           ==========================================================
  71.      *           For example: operation(2, '*', 4)
  72.      *           would compute the operation 2d*4d, which would return 8d.
  73.      *           ==========================================================
  74.      *
  75.      * @return The computation of the two doubles with the given operator.
  76.      */
  77.     public static double operation(double d1, char operator, double d2)
  78.     {
  79.         double result = 0;
  80.         switch(operator)
  81.         {
  82.             case '^':
  83.                 result = Math.pow(d1,d2);
  84.                 break;
  85.             case '*':
  86.                 result = d1 * d2;
  87.                 break;
  88.             case '/':
  89.                 result = d1 / d2;
  90.                 break;
  91.             case '+':
  92.                 result = d1 + d2;
  93.                 break;
  94.             case '-':
  95.                 result = d1 - d2;
  96.                 break;
  97.         }
  98.  
  99.         return result;
  100.     }
  101.  
  102.     /*
  103.     Next we need to do a few things at once in order to use our operator method:
  104.     First: we need to identify a single operation within a string.
  105.     Second: we need to correctly parse that operation into the three parts required for the operation method.
  106.  
  107.     First: A single operation can be defined as two doubles with an operation between them.
  108.     This definition however gets complicated due to the unique situation of the '-' sign both signifying a subtraction
  109.     and a negative number.
  110.  
  111.     The most important thing to correctly execute this subroutine is to know when there is a
  112.     negative number present within the operation. Since the core of this project is that when a parenthesis is reached,
  113.     we recurse, we need to identify the single case where a parenthesis is not containing an operation but simply a negative number
  114.  
  115.     For example: "3*(2*(-4))-4*(-1)"
  116.                         ^A  ^B
  117.         A: The case of the '-' at A is representing a negative number.
  118.         In evaluating weather we should recurse or not, a check needs to be made that there is actually an operation within.
  119.         This way when it comes time to partition the expression into individual operations, there are a set of assumptions the
  120.         method can have.
  121.  
  122.         A: '-' is representing a subtraction when and only when there is a number on both sides of the '-' or if the '-' is preceded by a ')'.
  123.         There is another edge case of if the '-' is at the very beginning of the expression string. This is because we can't evaluate
  124.         outside of the bounds of the string. It is required for the user to wrap a negative number in parentheses however the program
  125.         will inevitably need to unwrap the parentheses for evaluation.
  126.  
  127.         B: is representing a subtraction because there is a ')' preceding it.
  128.  
  129.         So a single operation can be defined by the following:
  130.         It can start with a '-' assuming a number does not precede it. It will contain an operator, and two doubles.
  131.         The doubles may be wrapped in parentheses. If so they need to be removed.
  132.  
  133.  
  134.  
  135.  
  136.     Now with the logic laid out, it's time to work on evaluating a string containing a single operation.
  137.     called parseOperation.
  138.     Goal:
  139.     The goal of parseOperation is to take a string containing a single operation, parse it into the appropriate individual
  140.     components and return a double that is the result of the operation. This method assumes the string is given with proper
  141.     syntax.
  142.     Parameters:
  143.      String op -> a string containing a single operation in correct syntax.
  144.     Returns: a double that is the result of the operation in the string.
  145.  
  146.     Therefore:
  147.         Step One:   If present, remove all parentheses from the operation.
  148.         Step Two:   Identify the true operator. in any given expression, there could be up two three operators present.
  149.                     If there is not a leading '-' the first operator is always the true operator.
  150.                     If there is a leading '-', the second operator is always the true operator.
  151.                     Save the index of the true operator as an integer for later use.
  152.         Step Three: We now have a clear and understandable format. We also have the index of the operator.
  153.                     We create two Double variables d1 and d2 initialized to zero.
  154.                     d1 = parseDouble(operation.subString(0, opIndex);
  155.                     d2 = parseDouble(operation.subString(opIndex+1);
  156.     */
  157.     public static double parseOperation(String operation)
  158.     {
  159.         double result = 0;
  160.  
  161.  
  162.         //Step One
  163.         StringBuffer operationBuff = new StringBuffer(operation);
  164.         for(int i = 0; i<operationBuff.length(); i++)
  165.         {
  166.             if(operationBuff.charAt(i) == '(' || operationBuff.charAt(i) == ')')
  167.             {
  168.                 operationBuff.deleteCharAt(i);
  169.             }
  170.         }
  171.         operation = operationBuff.toString();
  172.  
  173.  
  174.         //Step Two
  175.         int opIndex = 0;
  176.         int index = 0;
  177.         if(operation.charAt(0) == '-') index++;
  178.  
  179.         boolean operationFound = false;
  180.         while(index < operation.length() && !operationFound)
  181.         {
  182.             switch (operation.charAt(index))
  183.             {
  184.                 case '^':
  185.                 case '*':
  186.                 case'/':
  187.                 case '+':
  188.                 case '-':
  189.                     opIndex = index;
  190.                     operationFound = true;
  191.                     break;
  192.                 default:
  193.                     index++;
  194.                     break;
  195.             }
  196.         }
  197.  
  198.  
  199.         //Step Three
  200.         double d1 = parseDouble(operation.substring(0, opIndex));
  201.         double d2 = parseDouble(operation.substring(opIndex+1));
  202.  
  203.         result = operation(d1, operation.charAt(opIndex), d2);
  204.  
  205.  
  206.         return result;
  207.     }
  208.  
  209.  
  210.     /*
  211.     This will require us to simultaneously create the method that will correctly convert a single double in string form
  212.     to a true double for evaluation. We will call this method parseDouble.
  213.     Goal: To take a single double in string form and return it as a true double.
  214.     Parameters:
  215.     String dub -> a string containing a single double in correct format.
  216.     First we check if there is a negative in front of the string.
  217.     If so, we remove it and we set the negative flag to true.
  218.     Once the negative sign is removed and the flag is correctly set, we parse the double to decimal form
  219.     Then we multiply the double by -1 if the negative flag is true.
  220.  
  221.     Returns: The double that the string corresponds with.
  222.      */
  223.     public static double parseDouble(String theDouble)
  224.     {
  225.         double dub = 0;
  226.         boolean negative = false;
  227.         if(theDouble.charAt(0) == '-')
  228.         {
  229.             negative = true;
  230.             theDouble = theDouble.substring(1);
  231.         }
  232.         int index = theDouble.indexOf(".");
  233.         if(index == -1)
  234.         {
  235.             int pow = 0;
  236.             for(int i = theDouble.length()-1; i>= 0; i--)
  237.             {
  238.                 dub += (double) (theDouble.charAt(i) - 48) * Math.pow(10,pow);
  239.                 pow++;
  240.             }
  241.  
  242.         }else
  243.         {
  244.             //Go left
  245.             int pow = 0;
  246.             for(int i = index-1; i>=0; i--)
  247.             {
  248.                 dub += (double) (theDouble.charAt(i) - 48) * Math.pow(10,pow);
  249.                 pow++;
  250.             }
  251.             pow = -1;
  252.             //Go right
  253.             for(int i = index+1; i<theDouble.length(); i++)
  254.             {
  255.                 dub += (double) (theDouble.charAt(i) - 48) * Math.pow(10,pow);
  256.                 pow--;
  257.             }
  258.         }
  259.         if(negative)
  260.             dub *= -1;
  261.         return dub;
  262.     }
  263.  
  264.     /*
  265.     Now that we are able to successfully parse a single operation, we now need to be able to handle a string containing
  266.     several operations.
  267.     Assumptions:
  268.     All parentheses present are present because they house a single negative number and NOT and operation.
  269.  
  270.     We have to follow the order of operations. We must be mindful of '-' signs. They are NOT operators if:
  271.     they are at the beginning of the string, any other operation precedes them, or if a '(' precedes it.
  272.  
  273.     if any of these conditions are met, ignore it as a candidate for determining the next true operation.
  274.  
  275.     With these assumptions in place, we iterate through the string.
  276.     We assign a value to each of the operators to compare them.
  277.     '^' = 3; '*' and '/' = 2; '+' and '-' = 1;
  278.     We iterate through finding the operator with the highest value closest to the left.
  279.     Once this operator is found we need to find the two doubles surrounding it, so we can determine the upper
  280.     and lower bounds of the substring.
  281.     once found, we replace(lowerBound, upperBound, parseOperation(operation.substring(lowerBound, upperBound));
  282.  
  283.     We repeat this process until there are no more true operators.
  284.  
  285.     We will call this method parseSubExpression.
  286.     Goal:
  287.     The goal of this method is to evaluate a series of operations, eventually returning a single double.
  288.     Parameters:
  289.     String subExpression -> a string containing a sub-expression with the proper syntax. All parentheses are assumed to
  290.     be wrappers for negative numbers and NOT another sub-expression.
  291.  
  292.     ===================================================================================================================
  293.     It is important to understand that this method can't possibly be reached until we have gone as far into the
  294.     expression as possible and the evaluation method has identified that any parentheses remaining are not
  295.     sub-expressions but are in stead housing negative numbers!
  296.     ===================================================================================================================
  297.  
  298.  
  299.     Returns:
  300.     A double that is the result of the operations defined in the sub-expression.
  301.  
  302.     Step One:   Determine if any true operators remain. Create a boolean value to correspond with this.
  303.                 If not skip directly to final step.
  304.                 True operators are all operators. However a negative is not a true operator if it meets the criteria
  305.                 laid out above. We will do this with regex.
  306.     Step Two:   Assuming there is a true operator, we create a variable to represent the current operator value and the
  307.                 highest operator value. Then we iterate through the string and stop when we reach the end.
  308.                 Before we assign a '-' as the highest operator we simply need to to a quick check to see if it is a
  309.                 true operator.
  310.     Step Three: Once the true operator is found, we create two integer variables upperBound and lowerBound. These will
  311.                 contain the index of the beginning and the end of the target operation.
  312.                 To find the correct upper and lower bounds, we evaluate to the left from the index of the true operator,
  313.                 we stop when we reach another true operator, or the beginning of the string.
  314.                 Then we evaluate to the right and stop when we reach the next true operator or the end of the string.
  315.     Step Four:  Once the sub-operation is found, we replace it with the result of the operation. We set the index back
  316.                 to zero so we can begin evaluating the expression again.
  317.     Step Five:  Once this step is reached it is assumed that the only thing remaining in the string is a single double
  318.                 value. We can simply parse the double from the string and return it.
  319.      */
  320.     public static double parseSubExpression(String subExpression)
  321.     {
  322.         subExpression = deleteParentheses(subExpression);
  323.         //subExpression = deleteParentheses(subExpression);
  324.         double result = 0;
  325.         //Step One
  326.  
  327.         int index = 0;
  328.         StringBuffer bufferSubExpression = new StringBuffer(subExpression);
  329.  
  330.         /*
  331.  
  332.         Pattern p = Pattern.compile("[\\*\\+\\^\\/]|[0-9]\\-[0-9]");
  333.         Matcher m = p.matcher(bufferSubExpression);
  334.         boolean trueExpressionExists = m.find();
  335.         */
  336.  
  337.         //Step Two
  338.         //We're gonna make this a method called findTrueOperator()
  339.         /*
  340.         The assumption here is that there is always at least one true operator. It is highly likely that there always
  341.         is one. If not the loop is entered and exited.
  342.          */
  343.         while(findTrueOperator(bufferSubExpression.toString()) != -1)
  344.         {
  345.             index = findTrueOperator(bufferSubExpression.toString());
  346.             System.out.println(index);
  347.             //This means a true operator was found.
  348.             if(index != -1)
  349.             {
  350.                 //Step Three
  351.                 int lowerBound = 0;
  352.                 int upperBound = bufferSubExpression.length();
  353.                 int tempIndex = index;
  354.                 //We scan left and right looking for a true operator to set the upper and lower bounds.
  355.                 //TODO Brainstorm how to effectively identify the upper and lower bounds for the sub-operation!
  356.                 //Scan left
  357.                 index--;
  358.                 boolean operationFound = false;
  359.                 boolean numberFound = false;
  360.                 while(index >= 0 && !operationFound)
  361.                 {
  362.                     char c = bufferSubExpression.charAt(index);
  363.                     System.out.println(c);
  364.                     if (c >= '0' && c <= '9')
  365.                         numberFound = true;
  366.                     switch (c)
  367.                     {
  368.                         case '^':
  369.                         case '*':
  370.                         case '/':
  371.                         case '+':
  372.                            lowerBound = index+1;
  373.                            operationFound = true;
  374.                             break;
  375.                         case '-':
  376.                             if(negativeTest(bufferSubExpression.toString(), index))
  377.                             {
  378.                                 //I think we need to move this up 1
  379.                                 lowerBound = index+1;
  380.                                 operationFound = true;
  381.                             }
  382.                             break;
  383.                     }
  384.                     index--;
  385.                 }
  386.  
  387.                 index = tempIndex;
  388.                 /*
  389.                 WE ARE STILL HAVING SOME ISSUE SCANNING RIGHT! WHEN THERE IS A DOUBLE NEGATIVE
  390.                  */
  391.                 //Scan right
  392.                 index++;
  393.                 operationFound = false;
  394.                 numberFound = false;
  395.                 while(index < bufferSubExpression.length() && !operationFound)
  396.                 {
  397.                     char c = bufferSubExpression.charAt(index);
  398.                     if (c >= '0' && c <= '9')
  399.                         numberFound = true;
  400.  
  401.                     switch (c)
  402.                     {
  403.                         case '^':
  404.                         case '*':
  405.                         case '/':
  406.                         case '+':
  407.                             upperBound = index;
  408.                             operationFound = true;
  409.                             break;
  410.                         case '-':
  411.                             if(negativeTest(bufferSubExpression.toString(), index))
  412.                             {
  413.                                 upperBound = index;
  414.                                 operationFound = true;
  415.                             }
  416.                             break;
  417.  
  418.                     }
  419.                     index++;
  420.                 }
  421.                 index = tempIndex;
  422.                 System.out.println("(" + lowerBound + "," + upperBound + ")");
  423.                 //Step Four
  424.                 //Step four we replace the string now that we have the upper and lower bounds.
  425.                 System.out.println("Before: " + bufferSubExpression);
  426.                 System.out.println("Target Operation: "+ bufferSubExpression.substring(lowerBound, upperBound));
  427.                 String tempS = bufferSubExpression.toString();
  428.                 bufferSubExpression.delete(lowerBound, upperBound);
  429.                 bufferSubExpression.insert(lowerBound, parseOperation(tempS.substring(lowerBound,upperBound)));
  430.                 System.out.println("After: " + bufferSubExpression);
  431.                 //Not sure if this code is needed yet.
  432.                 /*
  433.                 m = p.matcher(bufferSubExpression);
  434.                 trueExpressionExists = m.find();
  435.  
  436.                 index++;
  437.                 if (trueExpressionExists) {
  438.                     index = 0;
  439.                 }
  440.                  */
  441.             }
  442.  
  443.  
  444.  
  445.         }
  446.         //Step Five
  447.         result = parseDouble(bufferSubExpression.toString());
  448.         return result;
  449.     }
  450.  
  451.     public static String deleteParentheses(String theExpression)
  452.     {
  453.         theExpression = theExpression.replaceAll("[\\(]|[\\)]", "");
  454.  
  455.  
  456.         return theExpression;
  457.     }
  458.  
  459.  
  460.     /**
  461.      *
  462.      * @param subExpression
  463.      * @return
  464.      */
  465.     public static int findTrueOperator(String subExpression) {
  466.  
  467.         int index = 0;
  468.         int currentOpVal = -1;
  469.         int highestOpVal = -1;
  470.         int operatorIndex = -1;
  471.         while (index < subExpression.length()) {
  472.             switch (subExpression.charAt(index)) {
  473.                 case '^':
  474.                     currentOpVal = 3;
  475.                     break;
  476.                 case '*':
  477.                 case '/':
  478.                     currentOpVal = 2;
  479.                     break;
  480.                 case '+':
  481.                     currentOpVal = 1;
  482.                     break;
  483.                 case '-':
  484.                     if(negativeTest(subExpression, index))
  485.                         currentOpVal = 1;
  486.                     break;
  487.             }
  488.  
  489.             if (currentOpVal > highestOpVal) {
  490.                 highestOpVal = currentOpVal;
  491.                 operatorIndex = index;
  492.             }else index++;
  493.  
  494.         }
  495.         if(highestOpVal == -1)
  496.             operatorIndex = -1;
  497.         else System.out.println("Target Operator: " + subExpression.charAt(operatorIndex));
  498.         return operatorIndex;
  499.     }
  500.  
  501.     /*
  502.         We will call this little helper method negativeTest
  503.         It will return a boolean true or false. It has two arguments, the subExpression to evaluate, and
  504.         the index of the negative number. It will be helpful to quickly check if a given '-' operator is a true
  505.         operator throughout the steps of this program.
  506.      */
  507.     public static boolean negativeTest(String subExpression, int index)
  508.     {
  509.  
  510.         boolean trueOperator = false;
  511.         if (index != 0) {
  512.             //System.out.println(subExpression.substring(index - 1, index + 2));
  513.             Pattern testP = Pattern.compile("[0-9]\\-[0-9]|[0-9]\\-[(]|[)]\\-[0-9]|[0-9]\\-\\-");
  514.             //System.out.println("Negative Test On: " + subExpression.substring(index - 1, index + 2));
  515.             Matcher testM = testP.matcher(subExpression.substring(index - 1, index + 2));
  516.             if (testM.find()) {
  517.                 trueOperator = true;
  518.             }
  519.         }
  520.  
  521.  
  522.         return trueOperator;
  523.     }
  524.  
  525.  
  526.     /*
  527.     FINALLY!
  528.     Now we need to implement the recursion. We parse the main expression with recursion, we keep doing this until we
  529.     reach a single value
  530.     We will call this method evaluate().
  531.  
  532.     First let us lay out the assumptions.
  533.     Assumptions:
  534.     The expression MUST have correct syntax as laid out in the API.
  535.     Any parenthesis that do NOT house an expression are to be ignored! (Wait or do they have to be ignored?)
  536.  
  537.  
  538.     When we reach a parenthesis, we do the following:
  539.     Identify the index of the upper and lower bounds of the parenthesis.
  540.     create a temp copy of the string
  541.     REMOVE the expression in between the bounds
  542.     REMOVE the parentheses
  543.     Call recursion on the subExpression and put the result at the index of the LOWER BOUNDS
  544.     =================================================================================
  545.     The above section is the recursion phase. The sentinel for this phase is that there are no more remaining true
  546.     operations in the sub-expression.
  547.  
  548.     Before we get to that we have to go on to phase two:
  549.     The assumption at this point is that any parentheses that are present at this point DO NOT represent a sub-expression
  550.     With this assumption satisfied, we simply call and return parseSubOperation of the string.
  551.  
  552.     This repeats until we go as deep into the expression as we possibly can. Working from the inner most expression
  553.     outwards.
  554.  
  555.     Step One:   We iterate through the expression and stop at a parenthesis.
  556.                 We need to identify weather this parentheses is housing
  557.      */
  558.     public static double evaluate(String theExpression)
  559.     {
  560.         double result = 0;
  561.         StringBuffer bufferExpression = new StringBuffer(theExpression);
  562.         //Step One
  563.         int index = 0;
  564.         int pcount = 0;
  565.         int lowerBound = 0;
  566.         int upperBound = bufferExpression.length();
  567.         boolean lowerFound = false;
  568.         boolean upperFound = false;
  569.         while(hasParentheses(bufferExpression.toString()))
  570.         {
  571.             for(int i = 0; i < bufferExpression.length(); i++)
  572.             {
  573.                 //System.out.println(e.charAt(i));
  574.                 int j = 0;
  575.                 if (bufferExpression.charAt(i) == '(') {
  576.                     //Okay we need to partition, now we need to find the index of the matching parenthesis.
  577.                     lowerBound = i;
  578.                     j = i+1;
  579.                     int pCount = 1;
  580.                     while (pCount != 0) {
  581.  
  582.  
  583.                         if (bufferExpression.charAt(j) == '(')
  584.                             pCount++;
  585.                         if (bufferExpression.charAt(j) == ')')
  586.                             pCount--;
  587.  
  588.                         if (pCount == 0) {
  589.                             //System.out.println("deleting");
  590.                             upperBound = j + 1;
  591.                         } else j++;
  592.                         //System.out.println("Loop: " + j +"\npCount: " + pCount);
  593.                     }
  594.                 }
  595.             }
  596.  
  597.  
  598.             String temp = bufferExpression.toString();
  599.             bufferExpression = bufferExpression.delete(lowerBound,upperBound);
  600.             bufferExpression.insert(lowerBound, "" + evaluate(temp.substring(lowerBound+1, upperBound-1)));
  601.         }
  602.  
  603.  
  604.  
  605.  
  606.         //By this step we assume there are no more parenthesis that contain a sub-expression.
  607.         result = parseSubExpression(bufferExpression.toString());
  608.         System.out.println("RESULT: " + bufferExpression.toString());
  609.         return result;
  610.     }
  611.  
  612.     //Work on this later
  613.     public static boolean hasParentheses(String theExpression)
  614.     {
  615.         Pattern p = Pattern.compile("[\\(]|[\\)]");
  616.         Matcher m = p.matcher(theExpression);
  617.  
  618.         return m.find();
  619.     }
  620.  
  621.     public static void main(String args[])
  622.     {
  623.         /*
  624.         SOLVED!
  625.         Problem statement: It seems as if the parseSubExpression method is not correctly identifying
  626.         the correct target operation every time. I need to re-evaluate the logic in that step.
  627.         Start by breaking down what the components of a single operation are. Then I need to
  628.         evaluate how to properly identify when we have found our operation.
  629.  
  630.         We need to start by listing the assumptions I am making
  631.         Assumptions:
  632.         The sub-expression does not contain invalid characters.
  633.         The sub-expression only contains parentheses wrapping a negative number.
  634.  
  635.         Obeservations:
  636.         It seems as if two things are happening.
  637.         Firstly, the incorrect operation is being displayed in the target operation printout.
  638.         The printout is also incomplete meaning something is wrong with the evaluation of the lower and upper
  639.         bounds of the expression. Write out this logic on paper so I can better understand what is going on here.
  640.          */
  641.  
  642.  
  643.         /*
  644.         So subExpression is not identifying the proper segment to evaluate!!
  645.         TODO: FIX THAT^^^^
  646.          */
  647.  
  648.         //System.out.println(hasParentheses("2212354"));
  649.         System.out.println(evaluate("(2+4)-(1+1)^2-3-2+4"));
  650.         char c = '4';
  651.  
  652.  
  653.  
  654.     }
  655. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement