(十三) 表达式生成器

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

完美

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值