Krolyxon
Commit be3ed51

Branches

Refs →

jcalbe3ed51

initial commit

Author
krolxon
Date
2024-02-14 21:23 +0530
Parents
None
Commit
be3ed5190773c168d101425fc9b6dbfbc754fa6b

+151 −0

2 files changed

  1. A Calculator.java +8 −0
  2. A Parser.java +143 −0
A Calculator.java View
@@ -0,0 +1,8 @@
1+public class Calculator {
2+ public static void main(String[] args) {
3+ String expr = "(36 * 3 + 9 * 7) * (84 / 12) * 5";
4+ Parser p = new Parser(expr);
5+ String postfix = p.toPostFix();
6+ System.out.println(p.evalExpr(postfix));
7+ }
8+}
A Parser.java View
@@ -0,0 +1,143 @@
1+/* Todo
2+* - Fix Substraction errors
3+* - Add support for trigonometric functions
4+* - Remove all edge cases
5+*/
6+
7+import java.util.Stack;
8+import java.util.StringJoiner;
9+
10+public class Parser {
11+ private String expr;
12+ private Stack<Character> operatorStack;
13+
14+ public Parser(String infixExpr) {
15+ expr = infixExpr.trim().replaceAll("\\s", ""); // remove whitespaces
16+ }
17+
18+ public static boolean isOperand(char c) {
19+ switch (c) {
20+ case '1':
21+ case '2':
22+ case '3':
23+ case '4':
24+ case '5':
25+ case '6':
26+ case '7':
27+ case '8':
28+ case '9':
29+ return true;
30+ default:
31+ return false;
32+ }
33+ }
34+
35+ public static boolean isOperand(String c) {
36+ return isOperand(c.charAt(0));
37+ }
38+
39+ public int getPresedence(char c) {
40+ switch (c) {
41+ case '^':
42+ return 3;
43+ case '/':
44+ return 2;
45+ case '*':
46+ return 2;
47+ case '+':
48+ return 1;
49+ case '-':
50+ return 1;
51+ default:
52+ return -1;
53+ }
54+ }
55+
56+ public boolean hasLeftAssociativity(char c) {
57+ if (c == '^') {
58+ return false;
59+ } else {
60+ return true;
61+ }
62+ }
63+
64+ public String toPostFix() {
65+ operatorStack = new Stack<>();
66+ StringJoiner output = new StringJoiner(" ");
67+ StringBuilder operand = new StringBuilder();
68+ char[] infix = expr.replaceAll(" ", "").toCharArray();
69+
70+ // Main Expression Iteration
71+ for (int i = 0; i < infix.length; i++) {
72+ char c = infix[i];
73+ if (isOperand(c)) {
74+ operand.append(infix[i]);
75+ if (i < infix.length - 1) {
76+ continue;
77+ }
78+ }
79+
80+ if (operand.length() > 0) {
81+ output.add(operand.toString());
82+ operand = new StringBuilder();
83+ }
84+
85+ if (c == '(') {
86+ operatorStack.push(c);
87+ } else if (c == ')') {
88+ while (!operatorStack.isEmpty() && operatorStack.peek() != '(') {
89+ output.add(operatorStack.pop().toString());
90+ }
91+ operatorStack.pop();
92+ } else {
93+ while (!operatorStack.isEmpty() && getPresedence(c) <= getPresedence((char) operatorStack.peek())
94+ && hasLeftAssociativity(c)) {
95+ output.add(operatorStack.pop().toString());
96+ }
97+ operatorStack.push(c);
98+ }
99+ }
100+
101+ while (!operatorStack.isEmpty()) {
102+ if (operatorStack.peek() == '(') {
103+ return "This expression is invalid";
104+ }
105+ output.add(operatorStack.pop().toString());
106+ }
107+
108+ // last digit gets duplicate entry for some reason, so have to remove it.
109+ String op = output.toString();
110+ return op.substring(0, op.length() -2);
111+ }
112+
113+ private Double evaluate(String operator, Double op1, Double op2) {
114+ switch (operator.charAt(0)) {
115+ case '+':
116+ return op2 + op1;
117+ case '-':
118+ return op2 - op1;
119+ case '*':
120+ return op2 * op1;
121+ case '/':
122+ return op1 / op2;
123+ case '^':
124+ return (Math.pow(op2, op1));
125+ default:
126+ return 0.0;
127+ }
128+ }
129+
130+ public double evalExpr(String postfix) {
131+ Stack<Double> stack = new Stack<Double>();
132+ for (String c : postfix.split(" ")) {
133+ if (isOperand(c)) {
134+ stack.push(Double.parseDouble(c));
135+ } else {
136+ Double op1 = (Double) (stack.pop());
137+ Double op2 = (Double) (stack.pop());
138+ stack.push(evaluate(c, op2, op1));
139+ }
140+ }
141+ return stack.pop();
142+ }
143+}