该实现可以计算复杂的计算表达式,做了几个测试通过,如下所示:
+(12.3 - 2.3 * 1) - 10/3 +- 2
-pow(min(1 + 2, 2),-1 * abs(max(1,1/-4+1/4)))
由于所有的复杂表达式都可以拆解为二元运算,或者一元运算,我们定义了一些基础的运算符,如下枚举,如果需要其他的可以自己在枚举中添加,并且在NumericalCalculator.singleCal(); 这个方法中实现即可。
public enum EmOperator { ADD("+", 2, 1,"加法"), SUB("-", 2, 1, "减法"), MULTIPLY("*", 2, 2, "乘法"), DIVIDE("/", 2, 2, "除法"), MOD("%", 2, 2, "取模"), POW("pow", 2, 3, "幂函数"), SQRT("sqrt", 1, 3, "平方根"), ABS("abs", 1, 3, "绝对值"), LOG("log", 1, 3, "自然对数"), LOG10("log10", 1, 3, "常用对数"), CEIL("ceil", 1, 3, "常用对数"), EXP("exp", 1, 3, "指数函数"), MAX("max", 2, 3, "最大值"), MIN("min", 2, 3, "最小值"), LEFT_BRACKET("(", 0, Integer.MAX_VALUE, "左括号"), RIGHT_BRACKET(")", 0, Integer.MAX_VALUE, "右括号"), ; //表达式,目前还没用,可使用反射调用某个对象的expression方法,需要加参数类型数组字段。 private String expression; //运算符参数个数 private int paramNumber; //运算符优先级 private int priority; //描述 private String desc; EmOperator(String expression, int paramNumber,int priority, String desc) { this.expression = expression; this.paramNumber = paramNumber; this.priority = priority; this.desc = desc; } public static boolean isSimpleOperator(String expression) { return ADD.expression.equals(expression) || SUB.expression.equals(expression) || LEFT_BRACKET.expression.equals(expression) || RIGHT_BRACKET.expression.equals(expression) || MULTIPLY.expression.equals(expression) || DIVIDE.expression.equals(expression) || MOD.expression.equals(expression); } public static EmOperator getByExpression(String expression) { for (EmOperator operator : EmOperator.values()) { if (operator.expression.equals(expression)) { return operator; } } return null; } public String getExpression() { return expression; } public void setExpression(String expression) { this.expression = expression; } public int getParamNumber() { return paramNumber; } public void setParamNumber(int paramNumber) { this.paramNumber = paramNumber; } public int getPriority() { return priority; } public void setPriority(int priority) { this.priority = priority; } public String getDesc() { return desc; } public void setDesc(String desc) { this.desc = desc; } }
计算器类:import java.math.BigDecimal; import java.math.RoundingMode; import java.util.ArrayList; import java.util.List; import java.util.Stack; public class NumericalCalculator { //操作数栈 /* private Stack<EmOperator> opStack = new Stack<EmOperator>(); //数据栈 private Stack<BigDecimal> dataStack = new Stack<BigDecimal>();*/ //负号替代符 private static final char NEGATIVE_SIGN = '#'; //小数点 private static final char RADIX_POINT = '.'; //表达式占位符 private static final char EXPRESSION_PLACEHOLDER = '$