spring 里面有工具来计算数学表达式如下, 那么面对一个新的表达式, 我们要做的就是先转成Spel 表达式(字符串). 然后再用spring 的spel 工具来计算
@Test
public void demonCalculation() {
EvaluationContext context = new StandardEvaluationContext();
context.setVariable("B", -2.1);
context.setVariable("C", 1999.3);
Expression exp = new SpelExpressionParser().parseExpression("T(java.lang.Math).min(#B , #C)");
double value = (double) exp.getValue(context);
Assertions.assertEquals(-2.1, value);
Expression exp2 = new SpelExpressionParser().parseExpression("T(java.lang.Math).abs(#B)");
double value2 = (double) exp2.getValue(context);
Assertions.assertEquals(2.1, value2);
Expression exp3 = new SpelExpressionParser().parseExpression("#B + #C");
double value3 = (double) exp3.getValue(context);
Assertions.assertEquals(1997.2, value3);
Expression exp4 = new SpelExpressionParser().parseExpression("T(java.lang.Math).max(#B , #C)");
double value4 = (double) exp4.getValue(context);
Assertions.assertEquals(1999.3, value4);
}
式子呢, 无非是式子-操作符-因子, 式子-操作符-式子 因子-操作符-因子 等等的排列组合. 我们把式子和因子抽象出来
public interface Splable {
default void setNeedBracket(boolean needBracket){};
default int getOrder(){
return Integer.MAX_VALUE;
};
StringBuffer getExp();
StringBuffer getSplExp();
}
表达式类
public class SplWrapper implements Splable {
int order;
boolean needBracket;
StringBuffer splExp;
StringBuffer exp;
public int getOrder() {
return order;
}
public void setOrder(int order) {
this.order = order;
}
public void setNeedBracket(boolean needBracket) {
this.needBracket = needBracket;
}
public SplWrapper(int order, StringBuffer splExp, StringBuffer exp) {
this.order = order;
this.needBracket = false;
this.splExp = splExp;
this.exp = exp;
}
private StringBuffer generateExp(StringBuffer str) {
StringBuffer s = new StringBuffer();
if (needBracket)
s.append("(");
s.append(str);
if (needBracket)
s.append(")");
return s;
}
@Override
public StringBuffer getExp() {
return generateExp(exp);
}
@Override
public StringBuffer getSplExp() {
return generateExp(splExp);
}
}
因子类
public enum SmaFactor implements Splable {
AAA("BBB");
private String factorStr;
SmaFactor(String factorStr) {
this.factorStr = factorStr;
}
@Override
public StringBuffer getExp() {
return new StringBuffer(factorStr);
}
@Override
public StringBuffer getSplExp() {
return new StringBuffer("#").append(name());
}
}
操作符定义
public enum MathOperator {
PLUS(" + ", "+", false, 1),
MINUS(" - ", "-", false, 1),
MULTIPLY(" * ", "*", false, 2),
DIVIDED_BY(" / ", "/", false, 2),
MIN(" MIN", "T(com.util.math.BigDecimalMath).min", true, Integer.MAX_VALUE),
MAX(" MAX", "T(com.util.math.BigDecimalMath).max", true, Integer.MAX_VALUE),
ABS(" ABS", "T(com.util.math.BigDecimalMath).abs", true, Integer.MAX_VALUE);
private String display;
private String splExpression;
private int order;
MathOperator(String display, String spelExpression, boolean needBrackets, int order) {
this.display = display;
this.splExpression = spelExpression;
this.order = order;
}
public String getDisplay() {
return display;
}
public String getSplExpression() {
return splExpression;
}
public int getOrder() {
return order;
}
}
操作符
public class InfixOperator implements Operator {
private MathOperator operator;
@Override
public MathOperator getOperator() {
return operator;
}
public StringBuffer generateSplExp(Splable s1, Splable s2) {
return s1.getSplExp().append(getOperator().getSplExpression()).append(s2.getSplExp());
}
public StringBuffer generateExp(Splable s1, Splable s2) {
return s1.getExp().append(getOperator().getDisplay()).append(s2.getExp());
}
public InfixOperator(MathOperator operator) {
this.operator = operator;
}
}
重载操作符
operator fun Splable.plus(s: Splable): SplWrapper = InfixOperator(MathOperator.PLUS).execute(this, s)
operator fun Splable.minus(s: Splable): SplWrapper = InfixOperator(MathOperator.MINUS).execute(this, s)
operator fun Splable.times(s: Splable): SplWrapper = InfixOperator(MathOperator.MULTIPLY).execute(this, s)
operator fun Splable.div(s: Splable): SplWrapper = InfixOperator(MathOperator.DIVIDED_BY).execute(this, s)
fun abs(s: Splable): SplWrapper = Abs().execute(s)
fun min(s1: Splable, s2: Splable): SplWrapper = PrefixOperator(MathOperator.MIN).execute(s1, s2)!!
fun max(s1: Splable, s2: Splable): SplWrapper = PrefixOperator(MathOperator.MAX).execute(s1, s2)!!
测试类
@Test
fun canGenerateExpression() {
val exp = BI - BIC + IE - ILDC * IEA
Assertions.assertEquals("#BI-#BIC+#IE-#ILDC*#IEA", exp.splExp.toString())
val exp2 = BIC * IEA - BIC / IE
Assertions.assertEquals("#BIC*#IEA-#BIC/#IE", exp2.splExp.toString())
val exp3 = (IE - ILDC) * IEA
Assertions.assertEquals("(#IE-#ILDC)*#IEA", exp3.splExp.toString())
val exp4 = BI - (BIC + IE - ILDC) * IEA + (BIC * IEA - BIC / IE) - FC
Assertions.assertEquals("#BI-(#BIC+#IE-#ILDC)*#IEA+(#BIC*#IEA-#BIC/#IE)-#FC", exp4.splExp.toString())
val exp5 = BI - BIC + abs(IE - ILDC) * IEA
Assertions.assertEquals("#BI-#BIC+T(com.util.math.BigDecimalMath).abs(#IE-#ILDC)*#IEA", exp5.splExp.toString())
val exp6 = BIC * min(IEA - BIC, IE)
Assertions.assertEquals("#BIC*T(com.util.math.BigDecimalMath).min((#IEA-#BIC),#IE)", exp6.splExp.toString())
}
完美