Guest User

ExpresionEvaluator.java

a guest
Feb 24th, 2022
94
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 7.61 KB | None | 0 0
  1. import java.util.Scanner;
  2.  
  3. //class for evaluating arithmetic expressions as double values, which are displayed rounded to 7 places,
  4. //with decimal points supressed for whole numbers. The unrounded double value is returned.
  5. public class ExprEvaluator
  6. {
  7. Scanner kb = new Scanner(System.in);
  8.  
  9. //class-wide variables:
  10. //Since expressions are evaluated one at a time, all evaluations can use the same two stacks.
  11. private static Stack1gen<Character> A = new Stack1gen<Character>(); //stack for operators
  12. private static Stack1gen<Double> B = new Stack1gen<Double>(); //stack for operands
  13.  
  14. //class-wide methods:
  15.  
  16. //method to print a double value that is an integer as an int
  17. public static void expressionOutput(double x)
  18. {
  19. if(x == (double)Math.round(x)) //if the answer is a whole number,
  20. //display without decimal point
  21. {
  22. int intAns = (int)x;
  23. System.out.println("value = " + intAns + '\n');
  24. }
  25. else
  26. {
  27. System.out.println("value = " + x + '\n');
  28. }
  29. }
  30.  
  31.  
  32. /*Expressions are evaluated from right to left, using a stack A of arithmetic
  33. operators and a stack B of operands. In this method, a single operation is
  34. evaluated by popping the current operator from A, its 2 operands from B, and by then
  35. performing the operation and pushing the result onto B as a double value.*/
  36.  
  37. private static void eval()
  38. {
  39. char op = A.pop(); //current operator
  40. double opnd1 = B.pop(); //operands
  41. double opnd2 = B.pop();
  42. double val = 0.0;
  43. switch (op) //evaluate
  44. {
  45. case '+':
  46. val = opnd1 + opnd2;
  47. break;
  48. case '-':
  49. val = opnd1 - opnd2;
  50. break;
  51. case '*':
  52. val = opnd1 * opnd2;
  53. break;
  54. case '/':
  55. val = opnd1/opnd2;
  56. break;
  57. }
  58. B.push(val); //push result onto B
  59. }
  60.  
  61. /* In this method, a parenthesized subexpression is
  62. evaluated by evaluating its operations on Stack A top-down
  63. until a right parenthesis is encountered on stack A;
  64. the right parenthesis is also popped from A*/
  65.  
  66. private static void evalDown()
  67. {
  68. do
  69. {
  70. eval();
  71. }while((A.getSize()>0) && (A.getTop() != ')'));
  72. if((A.getSize()>0) && (A.getTop() == ')'))
  73. {
  74. A.pop();
  75. }
  76. }
  77.  
  78.  
  79. //This method compares the current operator token in the input string to the operator
  80. //on top of stack A to determine precedence.
  81. private static boolean prec(char token, Stack1gen<Character> StackA)
  82. {
  83. char topOp = StackA.getTop();
  84. if((token == '*') || (token == '/'))
  85. {
  86. return true; //token has precedence, so it will be pushed onto A
  87. }
  88. else
  89. {
  90. if((topOp == '*') || (topOp == '/'))
  91. {
  92. return false; //operator at top of A has precedence
  93. }
  94. else
  95. {
  96. return true; //equal low-precedence operators or token is ')',
  97. // which is always pushed onto A
  98. }
  99. }
  100. }
  101.  
  102. //variables for an ExprEvaluator object
  103. private String e;
  104. private int p; //pointer to characters within the expression string e
  105.  
  106. //constructor
  107. public ExprEvaluator()
  108. {
  109. System.out.println("enter an expression");
  110. e = kb.nextLine(); //input an arithmetic expression as a line of keyboard input.
  111. p = e.length()-1;
  112. }
  113.  
  114. //parameterized constructor
  115. public ExprEvaluator(String ee)
  116. {
  117. e = ee;
  118. p = ee.length() - 1;
  119. }
  120.  
  121. public String getExpression()
  122. {
  123. return e;
  124. }
  125.  
  126.  
  127. //If a substring of e whose rightmost character is at position p
  128. //represents a number (possibly with a decimal point, possibly negative),
  129. //return the numerical value of the substring as a double value and
  130. //re-position p just to the left of the substring.
  131.  
  132. private double formNum()
  133. {
  134. double total = 0.0;
  135. int count = 0;
  136. int flag = 0;
  137. double mult = 1.0;
  138. char c,d;
  139. do
  140. {
  141. c = e.charAt(p); //examine the current character in the string (from right to left)
  142. if(c == '.')
  143. {
  144. flag = 1; //set a flag to remember that the character is a decimal point
  145. }
  146. else
  147. {
  148. //if the current character is a digit, convert to its
  149. //int value and include it in the value corresponding to the string.
  150. if((c >= '0') && (c<= '9'))
  151. {
  152. total = total + mult * (c-'0');
  153. mult = mult * 10.0;
  154. if(flag == 0)
  155. {
  156. count++; //count the number of digits to the right of a possible decimal point
  157. }
  158. }
  159. else
  160. {
  161. if(c == '_')
  162. {
  163. total = -total; //an underscore character represents a negative value
  164. }
  165. }
  166. }
  167. p--; //Prepare to move to the next character to the left.
  168. //This is a private non-static method because it changes the member variable p
  169. d = '?';
  170. if(p>= 0)
  171. {
  172. d = e.charAt(p); //the next character to the left
  173. }
  174. }while((p>=0) && (((d<='9')&&(d>='0'))||(d=='_')||(d=='.')));//check for a valid character
  175. if(flag==1)
  176. {
  177. total = total/Math.pow(10.0,count*1.0); //compute the value taking into account
  178. //the number of decimal places
  179. }
  180. return total;
  181. }
  182.  
  183. //This method uses the 2-stack approach to evaluate an expression (from right to left).
  184. //The result is rounded to 7 decimal places and displayed as explained in expressionOutput() above.
  185. //The original double value (unrounded) is returned to the calling program.
  186. //The code could be made more efficient (but more difficult to read) by using if-else-if-else...
  187. //as in formNum(); here we (unnecessarily) execute each if statement.
  188. public double evaluator()
  189. {
  190.  
  191. char token; //current token in the input expression
  192.  
  193. //loop to scan the string right to left
  194. do
  195. {
  196. token = e.charAt(p);
  197. if(token == ')')
  198. {
  199. A.push(token); //always push a right parenthesis to delimit a subexpression
  200. p--;
  201. }
  202.  
  203. //if the token is a left parenthesis,
  204. //evaluate the corresponding subexpression
  205. if(token == '(' )
  206. {
  207. evalDown();
  208. p--; //move beyond the left parenthesis
  209. }
  210.  
  211.  
  212. //If the token is an arithmetic operator of higher precedence
  213. //than the topmost operator on stack A, push the token onto A.
  214. if((token=='+')||(token=='-')||(token=='*')||(token=='/'))
  215. {
  216. if((A.getSize() == 0) || (prec(token, A) == true))
  217. {
  218. A.push(token);
  219. p--;
  220. }
  221. //If the token is an arithmetic operator of lower precedence than that
  222. //at the top of the stack, then evaluate the operation at the top of stack A.
  223. else
  224. {
  225. eval();
  226. }
  227. }
  228.  
  229. //if the token is the rightmost digit of a number or a decimal point on the right,
  230. //form the number as a double and push onto stack B
  231. if(((token<='9')&&(token>='0'))||(token=='.'))
  232. {
  233. B.push(formNum());
  234. }
  235.  
  236. }while(p >= 0);//continue to scan from right to left
  237.  
  238.  
  239. //after completely scanning the input string, evaluate any remaining operations
  240. while(A.getSize()>0)
  241. {
  242. eval();
  243. }
  244.  
  245. double x = B.pop();
  246.  
  247. //round the result to 7 places and then display
  248. expressionOutput((double)Math.round(x*10000000)/10000000.0);
  249.  
  250. return x; //return the original double value
  251. } //end of evaluator
  252.  
  253.  
  254. } //end of class
Advertisement
Add Comment
Please, Sign In to add comment