CalculatorSolver.java :  » Log » mhfinance » com » forsir » android » mhfinance » helper » Android Open Source

Android Open Source » Log » mhfinance 
mhfinance » com » forsir » android » mhfinance » helper » CalculatorSolver.java
package com.forsir.android.mhfinance.helper;

public class CalculatorSolver {
  public static String lastExpression = "";

  public static String solve(String expression, boolean usePrecedence) {
    expression = expression.replace("/*", "*");

    String result = ' ' + expression + ' ';
    char cha, operator;
    int leftPosition, rightPosition, operatorPosition;

    // resolve parentheses
    leftPosition = result.indexOf('(');
    while (leftPosition > 0) {
      int count = 1;
      // find right parentheses
      for (rightPosition = leftPosition + 1; rightPosition < result.length() - 1; rightPosition++) {
        cha = result.charAt(rightPosition);
        if (cha == ')') {
          count--;
          if (count == 0) {
            break;
          }
        }
        if (cha == '(') {
          count++;
        }
      }

      final String leftSubstring = prepareLeftString(result.substring(0, leftPosition));
      final String rightSubstring = prepareRightString(result.substring(rightPosition + 1));

      result = leftSubstring + solve(result.substring(leftPosition + 1, rightPosition), usePrecedence) + rightSubstring;
      leftPosition = result.indexOf('(');
    }

    // resolve single right parentheses
    rightPosition = result.indexOf(')');
    while (rightPosition > 0) {
      final String rightSubstring = prepareRightString(result.substring(rightPosition + 1));

      result = ' ' + solve(result.substring(1, rightPosition), usePrecedence) + rightSubstring;
      rightPosition = result.indexOf(')');
    }

    // Implement Compute
    for (int priority = 0; priority < 2; priority++) {
      if (usePrecedence) {
        operatorPosition = findOperatorByPriority(result, priority, 1);
      } else {
        operatorPosition = findFirstOperator(result, 1);
      }
      while (operatorPosition > 0) {
        operator = result.charAt(operatorPosition);
        leftPosition = getLeftOperandBegin(result, operatorPosition);
        rightPosition = getRightOperandEnd(result, operatorPosition);

        result = result.substring(0, leftPosition)
                + Compute(operator, result.substring(leftPosition, operatorPosition), result.substring(operatorPosition + 1, rightPosition))
                + result.substring(rightPosition);

        if (usePrecedence) {
          operatorPosition = findOperatorByPriority(result, priority, 2);
        } else {
          operatorPosition = findFirstOperator(result, 2);
        }

      }
    }
    return result.trim();
  }

  private static int findOperatorByPriority(String expresion, int priority, int from) {
    int pos1;
    int pos2;
    if (priority == 0) {
      pos1 = expresion.indexOf('/');
      pos2 = expresion.indexOf('*');
    } else {
      pos1 = expresion.indexOf('+');
      pos2 = expresion.indexOf('-', from);
    }

    if (pos1 == -1) {
      return pos2;
    }

    if (pos2 == -1) {
      return pos1;
    }

    if (pos1 < pos2) {
      return pos1;
    }
    return pos2;
  }

  private static int findFirstOperator(String expresion, int from) {
    final int[] pos = new int[] { 0, 0, 0, 0 };

    pos[0] = expresion.indexOf('/');
    pos[1] = expresion.indexOf('*');
    pos[2] = expresion.indexOf('+');
    pos[3] = expresion.indexOf('-', from);

    int min = -1;

    for (int i = 0; i < 4; i++) {
      if (pos[i] != -1) {
        if (min == -1) {
          min = pos[i];
        } else if (pos[i] < min) {
          min = pos[i];
        }
      }
    }
    return min;
  }

  private static int getLeftOperandBegin(String number, int operatorPosition) {
    char ch;
    operatorPosition--;
    do {
      ch = number.charAt(operatorPosition);
      if (!Character.isDigit(ch)) {
        if (ch != '.' && ch != ',') {
          break;
        }
      }
    } while (operatorPosition-- > 0);

    ch = number.charAt(operatorPosition);
    if (ch == '-') {
      ch = number.charAt(operatorPosition - 1);
      if (!Character.isDigit(ch)) {
        if (ch != '.' && ch != ',') {
          operatorPosition--;
        }
      }
    }

    return operatorPosition + 1;
  }

  private static int getRightOperandEnd(String number, int operatorPosition) {
    char ch;
    operatorPosition++;
    final int length = number.length();
    ch = number.charAt(operatorPosition);

    if (ch == '-' || ch == '+') {
      operatorPosition++;
    }

    do {
      ch = number.charAt(operatorPosition);
      if (!Character.isDigit(ch)) {
        if (ch != '.' && ch != ',') {
          return operatorPosition;
        }
      }
    } while (operatorPosition++ < length);
    return operatorPosition;
  }

  private static String prepareLeftString(String leftString) {
    final char cha = leftString.charAt(leftString.length() - 1);
    if (Character.isDigit(cha) || cha == '.' || cha == ',' || cha == ')') {
      leftString = leftString + '*';
    }

    if (!leftString.startsWith(" ")) {
      leftString = " " + leftString;
    }
    return leftString;
  }

  private static String prepareRightString(String rightString) {
    if (rightString.length() == 0) {
      return " ";
    }

    final char cha = rightString.charAt(0);
    if (Character.isDigit(cha) || cha == '.' || cha == ',' || cha == '(') {
      rightString = '*' + rightString;
    }

    if (!rightString.endsWith(" ")) {
      rightString = rightString + " ";
    }
    return rightString;
  }

  private static String prepareNumber(String number, String neutralNumber) {
    if (number.length() == 0 || number.contentEquals("-") || number.contentEquals("+")) {
      return neutralNumber;
    }

    // for easier computing
    number = number.replace(',', '.');
    final int position = number.lastIndexOf('.');

    if (position > 0) {
      number = number.substring(0, position).replace(".", "") + number.substring(position);
    }
    if (number.equals(".") || number.equals("-.") || number.equals("+.")) {
      return "0";
    }

    return number;
  }

  private static String Compute(char operator, String leftOperand, String rightOperand) {
    float left, right, result = 0;

    if (operator == '*' || operator == '/') {
      left = Float.parseFloat(prepareNumber(leftOperand, "1"));
      right = Float.parseFloat(prepareNumber(rightOperand, "1"));
    } else {
      left = Float.parseFloat(prepareNumber(leftOperand, "0"));
      right = Float.parseFloat(prepareNumber(rightOperand, "0"));
    }

    if (leftOperand.length() == 0) {
      if (rightOperand.length() == 0) {
        return "";
      }
      if (operator == '-') {
        return String.format("%.2f", -right);
      }
      return String.format("%.2f", right);
    }

    if (rightOperand.length() == 0) {
      return String.format("%.2f", left);
    }

    if (operator == '+') {
      result = left + right;
    }
    if (operator == '-') {
      result = left - right;
    }
    if (operator == '*') {
      result = left * right;
    }
    if (operator == '/') {
      result = left / right;
    }

    if (Float.isInfinite(result) || Float.isNaN(result)) {
      result = 0;
    }

    return String.format("%.2f", result);
  }
}
java2s.com  | Contact Us | Privacy Policy
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.