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);
}
}
|