aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorkrolxon <krolyxon@tutanota.com>2024-02-14 21:23:36 +0530
committerkrolxon <krolyxon@tutanota.com>2024-02-14 21:23:36 +0530
commitbe3ed5190773c168d101425fc9b6dbfbc754fa6b (patch)
tree517144dcf5958998470bfe28f560bf2faf0361c0
initial commit
-rw-r--r--Calculator.java8
-rw-r--r--Parser.java143
2 files changed, 151 insertions, 0 deletions
diff --git a/Calculator.java b/Calculator.java
new file mode 100644
index 0000000..492a572
--- /dev/null
+++ b/Calculator.java
@@ -0,0 +1,8 @@
+public class Calculator {
+ public static void main(String[] args) {
+ String expr = "(36 * 3 + 9 * 7) * (84 / 12) * 5";
+ Parser p = new Parser(expr);
+ String postfix = p.toPostFix();
+ System.out.println(p.evalExpr(postfix));
+ }
+}
diff --git a/Parser.java b/Parser.java
new file mode 100644
index 0000000..8135393
--- /dev/null
+++ b/Parser.java
@@ -0,0 +1,143 @@
+/* Todo
+* - Fix Substraction errors
+* - Add support for trigonometric functions
+* - Remove all edge cases
+*/
+
+import java.util.Stack;
+import java.util.StringJoiner;
+
+public class Parser {
+ private String expr;
+ private Stack<Character> operatorStack;
+
+ public Parser(String infixExpr) {
+ expr = infixExpr.trim().replaceAll("\\s", ""); // remove whitespaces
+ }
+
+ public static boolean isOperand(char c) {
+ switch (c) {
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ public static boolean isOperand(String c) {
+ return isOperand(c.charAt(0));
+ }
+
+ public int getPresedence(char c) {
+ switch (c) {
+ case '^':
+ return 3;
+ case '/':
+ return 2;
+ case '*':
+ return 2;
+ case '+':
+ return 1;
+ case '-':
+ return 1;
+ default:
+ return -1;
+ }
+ }
+
+ public boolean hasLeftAssociativity(char c) {
+ if (c == '^') {
+ return false;
+ } else {
+ return true;
+ }
+ }
+
+ public String toPostFix() {
+ operatorStack = new Stack<>();
+ StringJoiner output = new StringJoiner(" ");
+ StringBuilder operand = new StringBuilder();
+ char[] infix = expr.replaceAll(" ", "").toCharArray();
+
+ // Main Expression Iteration
+ for (int i = 0; i < infix.length; i++) {
+ char c = infix[i];
+ if (isOperand(c)) {
+ operand.append(infix[i]);
+ if (i < infix.length - 1) {
+ continue;
+ }
+ }
+
+ if (operand.length() > 0) {
+ output.add(operand.toString());
+ operand = new StringBuilder();
+ }
+
+ if (c == '(') {
+ operatorStack.push(c);
+ } else if (c == ')') {
+ while (!operatorStack.isEmpty() && operatorStack.peek() != '(') {
+ output.add(operatorStack.pop().toString());
+ }
+ operatorStack.pop();
+ } else {
+ while (!operatorStack.isEmpty() && getPresedence(c) <= getPresedence((char) operatorStack.peek())
+ && hasLeftAssociativity(c)) {
+ output.add(operatorStack.pop().toString());
+ }
+ operatorStack.push(c);
+ }
+ }
+
+ while (!operatorStack.isEmpty()) {
+ if (operatorStack.peek() == '(') {
+ return "This expression is invalid";
+ }
+ output.add(operatorStack.pop().toString());
+ }
+
+ // last digit gets duplicate entry for some reason, so have to remove it.
+ String op = output.toString();
+ return op.substring(0, op.length() -2);
+ }
+
+ private Double evaluate(String operator, Double op1, Double op2) {
+ switch (operator.charAt(0)) {
+ case '+':
+ return op2 + op1;
+ case '-':
+ return op2 - op1;
+ case '*':
+ return op2 * op1;
+ case '/':
+ return op1 / op2;
+ case '^':
+ return (Math.pow(op2, op1));
+ default:
+ return 0.0;
+ }
+ }
+
+ public double evalExpr(String postfix) {
+ Stack<Double> stack = new Stack<Double>();
+ for (String c : postfix.split(" ")) {
+ if (isOperand(c)) {
+ stack.push(Double.parseDouble(c));
+ } else {
+ Double op1 = (Double) (stack.pop());
+ Double op2 = (Double) (stack.pop());
+ stack.push(evaluate(c, op2, op1));
+ }
+ }
+ return stack.pop();
+ }
+}