【表达式】JAVA解析数学表达式 parsii 计算数学公式 表达式规则引擎 动态脚本语言

【表达式】JAVA解析数学表达式 parsii 计算数学公式 表达式规则引擎 动态脚本语言

1 MAVEN依赖

<!-- https://mvnrepository.com/artifact/com.scireum/parsii -->
<dependency>
    <groupId>com.scireum</groupId>
    <artifactId>parsii</artifactId>
    <version>4.0</version>
</dependency>

 或者使用 BigDecimal版本

<!-- https://mvnrepository.com/artifact/com.mpobjects/bdparsii -->
<dependency>
    <groupId>com.mpobjects</groupId>
    <artifactId>bdparsii</artifactId>
    <version>1.0.0</version>
</dependency>

2 DEMO

String exp = "2 + (7-5) * 3.14159 * x + sin(0)";  
  
// compile  
Scope scope = Scope.create();  
Expression parsiiExpr = Parser.parse(exp);  
Variable var = scope.getVariable("x");  
var.setValue(X_VALUE);  
  
// evaluate  
double result = parsiiExpr.evaluate();  
//OR 
//BigDecimal result = parsiiExpr.evaluate();  

  
System.out.println(result);//-> 2.0  

计算工具 支持%等



import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ReUtil;
import com.guanwei.study.string.CharUtil;
import com.mpobjects.bdparsii.eval.Expression;
import com.mpobjects.bdparsii.eval.Parser;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;

public class ParsiiDemo {


    public static void main(String[] args) throws Exception {

//        String exp = "2 + (7-5) * 3.14159 * x + sin(0)";
        String exp = "e^0.4*sign(3/12)";
        exp = "((1+2 -   0) × 100 +( 2X1)-2 ) ÷2 * 50.5% * 20% + {1-2} + [1+5] ﹣1·1 /1 ﹢1 ﹣1";
//        String exp = "e^0.4*√(3/12)";


        System.out.println("之前:" + exp);
        exp = ParsiiDemo.transitionFormula(exp);
        System.out.println("之后:" + exp);

// compile
//        Scope scope = new Scope();
        Expression parsiiExpr = Parser.parse(exp);
//        Variable var = scope.getVariable("x");
//        var.setValue(0);

// evaluate
        BigDecimal result = parsiiExpr.evaluate();

        System.out.println("计算结果:" + result);//-> 2.0
    }

    public static String transitionFormula(String exp){

//        exp = "+";
        //全角转半角
        exp = CharUtil.toDbc(exp);
        //所有字符转为小写
        exp = exp.toLowerCase();


        exp = exp
                .replaceAll("﹢", "+")
                .replaceAll("十", "+")
                .replaceAll("┼", "+")
                .replaceAll("╋", "+")
                .replaceAll("╬", "+")
                .replaceAll("﹣", "-")
                .replaceAll("一", "-")
                .replaceAll("x", "*")
                .replaceAll("×", "*")
                .replaceAll("╳", "*")
                .replaceAll("х", "*")
                .replaceAll("·", "*")
                .replaceAll("÷", "/")
                .replaceAll("\\{", "(")
                .replaceAll("}", ")")
                .replaceAll("\\[", "(")
                .replaceAll("]", ")")
        ;

        //包含百分号
        if(exp.contains("%")){
            //获取包含百分号的数字
            //List<String> resultFindAll = ReUtil.findAll("([\\d])*%|([\\d]).([\\d])*%", exp, 0, new ArrayList<String>());
            List<String> resultFindAll = ReUtil.findAll("([\\\\d])*%|(\\\\d{1,10}).([\\\\d])*%", exp, 0, new ArrayList<String>());




            if(CollUtil.isNotEmpty(resultFindAll)){
                for (String s : resultFindAll) {
                    s = s.trim();
                    String replace = s.replace("%", "");
                    BigDecimal bigDecimal = new BigDecimal(replace);
                    bigDecimal = bigDecimal.divide(new BigDecimal(100));
                    exp = exp.replaceAll(s, bigDecimal.toString());

                }
            }

            System.out.println(resultFindAll);
        }

        return exp;
    }


}

补充全角转半角的工具

CharUtil 

import cn.hutool.core.util.StrUtil;

/**
 * 字符工具
 */
public class CharUtil {



    /**
     * 半角转全角的函数(SBC case)
     * 全角空格为12288,半角空格为32,其他字符半角(33-126)与全角(65281-65374)的对应关系是:均相差65248
     *
     * @param input 任意字符串
     * @return 全角字符串
     */
    public static String toSbc(String input) {
        if (StrUtil.isBlank(input)) {
            return "";
        }
        char[] c = input.toCharArray();
        for (int i = 0; i < c.length; i++) {
            if (c[i] == 32) {
                c[i] = (char) 12288;
                continue;
            }
            if (c[i] < 127) {
                c[i] = (char) (c[i] + 65248);
            }
        }
        return new String(c);
    }


    /**
     * 全角转半角的函数(DBC case)
     * 全角空格为12288,半角空格为32 其他字符半角(33-126)与全角(65281-65374)的对应关系是:均相差65248
     *
     * @param input 任意字符串
     * @return 半角字符串
     */
    public static String toDbc(String input) {
        if (StrUtil.isBlank(input)) {
            return "";
        }
        char[] c = input.toCharArray();
        for (int i = 0; i < c.length; i++) {
            if (c[i] == 12288) {
                c[i] = (char) 32;
                continue;
            }
            if (c[i] > 65280 && c[i] < 65375) {
                c[i] = (char) (c[i] - 65248);
            }
        }
        return new String(c);
    }

    /**
     * 打印出java中所有Unicode编码的字符
     */
    private static void printAllCharacter() {
        for (int i = Character.MIN_VALUE; i <= Character.MAX_VALUE; ++i) {
            System.out.println(i + "   " + (char) i);
        }
    }

    public static void main(String[] args) {
        String str = "半角符号示例:,!~    全角符号示例:,!~";
        System.out.println("半角--->全角转换前:" + str);
        String sbcResult = toSbc(str);
        System.out.println("半角--->全角转换后:" + sbcResult);

        System.out.println("全角--->半角转换前:" + str);
        String dbcResult = toDbc(str);
        System.out.println("全角--->半角转换后:" + dbcResult);
        //打印出java所有字符
//    printAllCharacter();
    }

}

其他

QLExpress: 规则引擎 (gitee.com)

GitHub - alibaba/QLExpress: QLExpress is a powerful, lightweight, dynamic language for the Java platform aimed at improving developers’ productivity in different business scenes.

添加依赖

        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>QLExpress</artifactId>
            <version>3.2.7</version>
        </dependency>

代码

ExpressRunner runner = new ExpressRunner();
DefaultContext<String, Object> context = new DefaultContext<String, Object>();
context.put("a",1);
context.put("b",2);
context.put("c",3);
String express = "a+b*c+3";
Object r = runner.execute(express, context, null, true, false);
System.out.println(r);

JEval

依赖

<!-- https://mvnrepository.com/artifact/net.sourceforge.jeval/jeval -->
<dependency>
    <groupId>net.sourceforge.jeval</groupId>
    <artifactId>jeval</artifactId>
    <version>0.9.4</version>
</dependency>

代码 

String exp = "2 + (7-5) * 3.14159 * #{x} + sin(0)";  
  
// compile  
Evaluator jevalEvaluator = new Evaluator();  
jevalEvaluator.setVariables(Collections.singletonMap("x", Double.toString(X_VALUE)));  
  
// evaluate  
double result = Double.parseDouble(jevalEvaluator.evaluate(exp));  
  
System.out.println(result);//-> 2.0  

JEPLite

String exp = "2 + (7-5) * 3.14159 * x + sin(0)";  
  
// compile  
JEP jep = new JEP();  
jep.addVariable("x", X_VALUE);  
jep.parseExpression(exp);  
DoubleStack jepStack = new DoubleStack();  
  
// evaluate  
double result = jep.getValue(jepStack);  
  
System.out.println(result);//-> 2.0  

parsii

JEval

JEPLite

expr

Janino

MathEval

QLExpress

alibaba/QLExpress: QLExpress is a powerful, lightweight, dynamic language for the Java platform aimed at improving developers’ productivity in different business scenes. (github.com)

alibaba/QLExpress

QLExpress是一种功能强大、轻量级的Java平台动态语言,旨在提高开发人员在不同业务场景中的生产力。

由阿里的电商业务规则、表达式(布尔组合)、特殊数学公式计算(高精度)、语法分析、脚本二次定制等强需求而设计的一门动态脚本引擎解析工具。 在阿里集团有很强的影响力,同时为了自身不断优化、发扬开源贡献精神,于2012年开源。

QLExpress脚本引擎被广泛应用在阿里的电商业务场景,具有以下的一些特性:

  • 1、线程安全,引擎运算过程中的产生的临时变量都是threadlocal类型。
  • 2、高效执行,比较耗时的脚本编译过程可以缓存在本地机器,运行时的临时变量创建采用了缓冲池的技术,和groovy性能相当。
  • 3、弱类型脚本语言,和groovy,javascript语法类似,虽然比强类型脚本语言要慢一些,但是使业务的灵活度大大增强。
  • 4、安全控制,可以通过设置相关运行参数,预防死循环、高危系统api调用等情况。
  • 5、代码精简,依赖最小,250k的jar包适合所有java的运行环境,在android系统的低端pos机也得到广泛运用。

groovy

Groovy 教程_w3cschool

Apache Groovy是一种强大的、可选的类型化和动态语言,具有静态类型和静态编译功能,用于Java平台,目的在于通过简洁、熟悉和易于学习的语法提高开发人员的工作效率。它可以与任何Java程序顺利集成,并立即向您的应用程序提供强大的功能,包括脚本编写功能、特定于域的语言编写、运行时和编译时元编程以及函数式编程。
Groovy是一种基于JVM(Java虚拟机)的敏捷开发语言,它结合了Python、Ruby和Smalltalk的许多强大的特性,Groovy 代码能够与 Java 代码很好地结合,也能用于扩展现有代码。也是JVM的一个替代语言(替代是指可以用 Groovy 在Java平台上进行 Java 编程),使用方式基本与使用 Java代码的方式相同,该语言特别适合与Spring的动态语言支持一起使用,设计时充分考虑了Java集成,这使 Groovy 与 Java 代码的互操作很容易。(注意:不是指Groovy替代java,而是指Groovy和java很好的结合编程
 

流程规则引擎

dromara / liteFlow

轻量,快速,稳定,可编排的组件式规则引擎/流程引擎。 拥有全新设计的DSL规则表达式。 组件复用,同步/异步编排,动态编排,复杂嵌套规则,热部署,平滑刷新规则等等功能,让你加快开发效率!

Java中可以通过以下几种方式计算数学表达式: 1. 使用eval()函数 Java中可以使用eval()函数来计算一个字符串表达式,该函数需要引入ScriptEngineManager和ScriptEngine两个类,代码如下: ```java import javax.script.ScriptEngineManager; import javax.script.ScriptEngine; public class Main { public static void main(String[] args) throws Exception { ScriptEngineManager mgr = new ScriptEngineManager(); ScriptEngine engine = mgr.getEngineByName("JavaScript"); String mathExpr = "3+4*2"; System.out.println(engine.eval(mathExpr)); } } ``` 输出结果为11。 2. 使用第三方库 Java中也有一些第三方库可以用于计算数学表达式,比如JEP和Javaluator。 JEP是一个用于解析、评估和简化数学表达式Java库,可以实现高精度计算和符号计算。代码示例: ```java import com.singularsys.jep.*; import com.singularsys.jep.functions.*; import com.singularsys.jep.parser.*; import com.singularsys.jep.standard.*; import com.singularsys.jep.walkers.*; import java.util.*; public class Main { public static void main(String[] args) throws Exception { Jep jep = new Jep(); jep.addStandardFunctions(); jep.addStandardConstants(); String mathExpr = "3+4*2"; Node node = jep.parse(mathExpr); Object result = jep.evaluate(node); System.out.println(result); } } ``` 输出结果为11。 Javaluator是另一个用于解析计算数学表达式Java库,支持变量、函数、自定义操作符等。代码示例: ```java import com.fathzer.soft.javaluator.*; public class Main { public static void main(String[] args) throws Exception { ExpressionEvaluator evaluator = new ExpressionEvaluator(); String mathExpr = "3+4*2"; Double result = evaluator.evaluate(mathExpr); System.out.println(result); } } ``` 输出结果为11.0。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

我是Superman丶

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值