JEP:Java表达式分析器

JEP 是一个用于解析和计算数学表达式的 Java 类库。通过使用这个包你可以把公式看
作字符串并快速计算它们。其中内置了大量公共的数学函数和常量供用户使用。另外,你也
可以通过自定义变量、常量、函数等方式扩展 JEP
使用 JEP 计算一个字符串表达式包括两个步骤,如下图所示。首先是解析表达式,从
字符串结构解析为树形结构。表达式的树形结构表示允许接下来的简单、快速的表达式计算。

文档:Jep说明文档_jep,javajep-Java文档类资源-CSDN下载

测试代码:

        <!-- jep java表达式分析器 -->
        <dependency>
            <groupId>com.singularsys</groupId>
            <artifactId>jep</artifactId>
            <version>3.5</version>
            <classifier>trial</classifier>
        </dependency>
import com.singularsys.jep.PostfixMathCommandI;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

/**
 * @author lihai
 * Create Date: 2021-11-20
 */
@Data
@NoArgsConstructor
@AllArgsConstructor
public class JepFunctionPo {
    private String name;
    private PostfixMathCommandI function;
}
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.ObjectUtil;
import com.qms.ipqc.common.po.JepFunctionPo;
import com.quality.common.exception.DangerException;
import com.quality.common.exception.GeneralException;
import com.singularsys.jep.Jep;
import com.singularsys.jep.JepException;
import com.singularsys.jep.Variable;
import com.singularsys.jep.VariableTable;
import com.singularsys.jep.bigdecimal.BigDecComponents;
import com.singularsys.jep.functions.*;

import java.math.BigDecimal;
import java.math.MathContext;
import java.util.*;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author lihai
 * Create Date: 2021-11-20
 */
public class JepAnalysisUtil {

    public static List<JepFunctionPo> getDefaultJepFunctionPoList() {
        return Arrays.asList(
//                new JepFunctionPo("round", new Round()),
//                new JepFunctionPo("rint", new RInt()),
//                new JepFunctionPo("floor", new Floor()),
//                new JepFunctionPo("ceil", new Ceil()),
//                new JepFunctionPo("abs", new Abs()),
                new JepFunctionPo("sqrt", new SquareRoot()),
                new JepFunctionPo("SQRT", new SquareRoot())
        );
    }

    public static Jep newJep(List<JepFunctionPo> functions) {
        Jep jep = new Jep(new BigDecComponents(MathContext.DECIMAL128));
        if (ObjectUtil.isNotEmpty(functions)) {
            functions.forEach(function -> jep.addFunction(function.getName(), function.getFunction()));
        }
        return jep;
    }

    public static Jep parse(String expression) {
        Jep jep = newJep(getDefaultJepFunctionPoList());
        try {
            jep.parse(expression);
            return jep;
        } catch (Exception e) {
            throw new DangerException("JEP解析表达式失败:" + expression + ",请检查表达式是否合法!");
        }
    }

    public static BigDecimal analysis(String expression, Map<String, Object> variables) {
        Jep jep = parse(expression);
        try {
            if (ObjectUtil.isNotEmpty(variables)) {
                variables.forEach((k, v) -> {
                    try {
                        jep.addVariable(k, NumberUtil.parseNumber(v.toString()));
                    } catch (JepException e) {
                        throw new DangerException("JEP赋值异常:" + e.getMessage());
                    }
                });
            }
            return new BigDecimal(jep.evaluate().toString());
        } catch (JepException e) {
            throw new GeneralException("JEP计算异常:" + e.getMessage());
        }
    }

    public static Set<String> getVariables(String expression) {
        Jep jep = parse(expression);
        try {
            final VariableTable variableTable = jep.getVariableTable();
            final List<Variable> variables = new ArrayList<>(variableTable.getVariables());
            return variables.stream().filter(var -> var.getValue() == null).map(Variable::getName).collect(Collectors.toSet());
        } catch (Exception e) {
            throw new DangerException("获取JEP变量失败:" + expression);
        }
    }

    public static void checkExpressionVariables(String expression, Set<String> variables) {
        final Set<String> expressionVariables = getVariables(expression);
        for (String var : expressionVariables) {
            if (!variables.contains(var)) {
                throw new DangerException(String.format("表达式:%s 缺少变量:%s", expression, var));
            }
        }
    }

}

测试方法:

    @Test
    void jepAnalysis() {
        String expression = "sqrt(a-b+c*d/e)";
        Map<String, Object> params = new HashMap<String, Object>() {{
            put("a", 5);
            put("b", 1);
            put("c", 3);
            put("d", 2);
            put("e", 2);
        }};
        final BigDecimal analysis = JepAnalysisUtil.analysis(expression, params);
        System.out.println("计算结果:" + analysis);
    }

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值