Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- import java.util.*;
- import static java.lang.Double.NaN;
- import static java.lang.Double.valueOf;
- import static java.lang.Math.incrementExact;
- import static java.lang.Math.pow;
- /*
- * A calculator for rather simple arithmetic expressions
- *
- * This is not the program, it's a class declaration (with methods) in it's
- * own file (which must be named Calculator.java)
- *
- * NOTE:
- * - No negative numbers implemented
- */
- public class Calculator {
- // Here are the only allowed instance variables!
- // Error messages (more on static later)
- final static String MISSING_OPERAND = "Missing or bad operand";
- final static String DIV_BY_ZERO = "Division with 0";
- final static String MISSING_OPERATOR = "Missing operator or parenthesis";
- final static String OP_NOT_FOUND = "Operator not found";
- // Definition of operators
- final static String OPERATORS = "+-*/^";
- // Method used in REPL
- double eval(String expr) {
- if (expr.length() == 0) {
- return NaN;
- }
- List<String> tokens = tokenize(expr);
- List<String> postfix = infix2Postfix(tokens);
- return evalPostfix(postfix);
- }
- // ------ Evaluate RPN expression -------------------
- double evalPostfix(List<String> postfix) {
- Deque<String> stack = new ArrayDeque<String>();
- List<String> results = new ArrayList<String>();
- double a,b;
- if (postfix.size() == 1){
- return valueOf(postfix.get(0));
- }
- for (int i = 0; i < postfix.size() ; i++) {
- if(!isOperator(postfix.get(i))){
- stack.push(postfix.get(i));
- }
- else{
- a = Double.valueOf(stack.pop());
- b = Double.valueOf(stack.pop());
- stack.push(applyOperator(postfix.get(i), a, b)+"");
- }
- }
- return Double.valueOf(stack.pop());
- /*
- Deque<String> que = new ArrayDeque<String>();
- Double a,b, result;
- for (int i = 0; i < postfix.size(); i++) {
- if (!isOperator(postfix.get(i))){
- que.push(postfix.get(i));
- } else {
- List<double> results = new ArrayList<double>();
- a = valueOf(que.pop());
- b = valueOf(que.pop());
- result = applyOperator(postfix.get(i), a, b);
- }
- }
- return 0;
- */
- }
- boolean isOperator(String s){
- String[] operators = {"+","-", "*", "/", "^", "(", ")"};
- for (int i = 0; i < operators.length; i++) {
- if (operators[i].contains(s)){
- return true;
- }
- }
- return false;
- }
- double applyOperator(String op, double d1, double d2) {
- switch (op) {
- case "+":
- return d1 + d2;
- case "-":
- return d2 - d1;
- case "*":
- return d1 * d2;
- case "/":
- if (d1 == 0) {
- throw new IllegalArgumentException(DIV_BY_ZERO);
- }
- return d2 / d1;
- case "^":
- return pow(d2, d1);
- }
- throw new RuntimeException(OP_NOT_FOUND);
- }
- // ------- Infix 2 Postfix ------------------------
- List<String> infix2Postfix(List<String> infix) {
- String[] operators = {"+","-", "*", "/", "^", "(", ")"};
- List<String> postFix = new ArrayList<String>();
- Deque<String> que = new ArrayDeque<String>();
- int count = 0;
- boolean latestBracket = false;
- for (int i = 0; i < infix.size(); i++) {
- for (int j = 0; j < operators.length; j++) {
- if (!que.isEmpty() && !que.peek().contains("(")){
- latestBracket = false;
- } else if (!que.isEmpty()){
- latestBracket = true;
- }
- if (!infix.get(i).contains(operators[j])){
- count++;
- } else{
- if (latestBracket && !infix.get(i).contains("(") && !infix.get(i).contains(")")){
- que.push(infix.get(i));
- latestBracket = false;
- break;
- }
- if (infix.get(i).contains("(")){
- que.push(infix.get(i));
- latestBracket = true;
- } else if (infix.get(i).contains(")")) {
- int stackSize = que.size();
- for (int k = 0; k < stackSize; k++) {
- if (!que.peek().contains("(")){
- postFix.add(que.pop());
- } else {
- que.pop();
- break;
- }
- }
- } else {
- if (que.isEmpty()){
- que.push(infix.get(i));
- } else if (getPrecedence(que.peek()) > getPrecedence(infix.get(i))){
- String popper = que.peek();
- postFix.add(que.pop());
- while (true){
- if (!que.isEmpty() && que.peek().contains(popper)){
- postFix.add(que.pop());
- } else break;
- }
- que.push(infix.get(i));
- } else if (getPrecedence(que.peek()) == getPrecedence(infix.get(i))){
- if (getAssociativity(infix.get(i)) == Assoc.LEFT){
- postFix.add(que.pop());
- }
- que.push(infix.get(i));
- } else if (getPrecedence(que.peek()) < getPrecedence(infix.get(i))){
- que.push(infix.get(i));
- }
- }
- }
- }
- if (count == operators.length){
- postFix.add(infix.get(i));
- }
- count = 0;
- }
- int queSize = que.size();
- while(!que.isEmpty()){
- postFix.add(que.pop());
- }
- return postFix;
- }
- int getPrecedence(String op) {
- if ("+-".contains(op)) {
- return 2;
- } else if ("*/".contains(op)) {
- return 3;
- } else if ("^".contains(op)) {
- return 4;
- } else {
- throw new RuntimeException(OP_NOT_FOUND);
- }
- }
- Assoc getAssociativity(String op) {
- if ("+-*/".contains(op)) {
- return Assoc.LEFT;
- } else if ("^".contains(op)) {
- return Assoc.RIGHT;
- } else {
- throw new RuntimeException(OP_NOT_FOUND);
- }
- }
- enum Assoc {
- LEFT,
- RIGHT
- }
- // ---------- Tokenize -----------------------
- // List String (not char) because numbers (with many chars)
- List<String> tokenize(String expr) {
- // TODO
- List<String> tokens = new ArrayList<String>();
- StringTokenizer test = new StringTokenizer(expr,"[\\+\\-*/\\^ ()]+", true );
- while(test.hasMoreTokens()){
- tokens.add(test.nextToken());
- }
- for (int i = 0; i < tokens.size(); i++) {
- if (tokens.get(i).contains(" ")){
- tokens.remove(i);
- i = 0;
- }
- }
- return tokens;
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment