繁体   English   中英

Java中计算数学表达式的方法

[英]Method for evaluating math expressions in Java

在我的一个项目中,我想添加一个用户可以在公式中提供的功能,例如

sin (x + pi)/2 + 1

我在我的 Java 应用程序中使用的

/**
 * The formula provided by the user
 */
private String formula; // = "sin (x + pi)/2 + 1"

/*
 * Evaluates the formula and computes the result by using the
 * given value for x
 */
public double calc(double x) {
    Formula f = new Formula(formula);
    f.setVar("x", x);
    return f.calc();
    // or something similar
}

如何评估数学表达式?

还有exp4j ,一个基于Dijkstra's Shunting Yard Shunting Yard的表达式评估器。 它在 Apache 许可证 2.0 下免费提供和重新分发,大小只有大约 25KB,并且非常易于使用:

Calculable calc = new ExpressionBuilder("3 * sin(y) - 2 / (x - 2)")
        .withVariable("x", varX)
        .withVariable("y", varY)
        .build()
double result1=calc.calculate();

使用较新的 API 版本(如0.4.8

Expression calc = new ExpressionBuilder("3 * sin(y) - 2 / (x - 2)")
    .variable("x", x)
    .variable("y", y)
    .build();
double result1 = calc.evaluate();

还有一个工具可以在exp4j 中使用自定义函数。

为了扩展列表,我也刚刚完成了一个:

https://github.com/uklimaschewski/EvalEx

EvalEx 是一个方便的 Java 表达式评估器,它允许评估简单的数学和布尔表达式。

主要特征:

  • 使用 BigDecimal 进行计算和结果
  • 单类实现,非常紧凑
  • 不依赖于外部库
  • 可设置精度和舍入模式
  • 支持变量
  • 标准布尔和数学运算符
  • 标准的基本数学和布尔函数
  • 可以在运行时添加自定义函数和运算符

例子:

BigDecimal result = null;

Expression expression = new Expression("1+1/3");
result = expression.eval():
expression.setPrecision(2);
result = expression.eval():

result = new Expression("(3.4 + -4.1)/2").eval();

result = new Expression("SQRT(a^2 + b^2").with("a","2.4").and("b","9.253").eval();

BigDecimal a = new BigDecimal("2.4");
BigDecimal b = new BigDecimal("9.235");
result = new Expression("SQRT(a^2 + b^2").with("a",a).and("b",b).eval();

result = new Expression("2.4/PI").setPrecision(128).setRoundingMode(RoundingMode.UP).eval();

result = new Expression("random() > 0.5").eval();

result = new Expression("not(x<7 || sqrt(max(x,9)) <= 3))").with("x","22.9").eval();

这取决于您想要评估的表达式的复杂程度,但对于简单的表达式,java 有一个运行良好的 javascript 引擎:

import javax.script.*;
public class EvalScript {
public static void main(String[] args) throws Exception {
    // create a script engine manager
    ScriptEngineManager factory = new ScriptEngineManager();
    // create a JavaScript engine
    ScriptEngine engine = factory.getEngineByName("JavaScript");
    // evaluate JavaScript code from String
    Object obj = engine.eval("1+2");
    System.out.println( obj );
    }
}

包含广泛数学集合的漂亮数学解析器 - mXparser - 请参见示例:

示例 1:

import org.mariuszgromada.math.mxparser.*;
...
...
Argument x = new Argument("x = pi");
Expression e = new Expression("sin(x + pi)/2 + 1", x);
mXparser.consolePrintln("Res 1: " + e.getExpressionString() + " = " + e.calculate());
x.setArgumentValue(2);
mXparser.consolePrintln("Res 2: " + e.getExpressionString() + " = " + e.calculate());

结果:

[mXparser-v.4.0.0] Res 1: sin(x + pi)/2 + 1 = 1.0
[mXparser-v.4.0.0] Res 2: sin(x + pi)/2 + 1 = 0.545351286587159

示例 2:

import org.mariuszgromada.math.mxparser.*;
...
...
Function f = new Function("f(x) = sin(x + pi)/2 + 1");
Expression e = new Expression("f(pi)", f);
mXparser.consolePrintln("Res: " + e.getExpressionString() + " = " + e.calculate());

结果:

[mXparser-v.4.0.0] Res: f(pi) = 1.0

为了更好地理解,请遵循mXparser 教程mXparser 数学集合

最近发现 - 如果您想尝试语法(并查看高级用例),您可以下载由 mXparser 提供支持的标量计算器应用程序

最好的祝福

在列表中添加另一个选项,我编写了 Jep Java,它作为sourceforge 上的一个开源项目而广受欢迎。

它支持表达式解析的所有基本常见任务。 但如果你想自定义它,它也会增加很多可扩展性。 许多用户称赞该库编写得特别好且易于使用。 查看 sourceforge 评论!

这是一个带有单个变量的简单示例:

import com.singularsys.jep.Jep;

Jep jep = new Jep();
jep.addVariable("x", 10);
jep.parse("x+1");
Object result = jep.evaluate();
System.out.println("x + 1 = " + result);

这将打印“x + 1 = 11”。 您可以更改变量的值并再次快速评估表达式。

后来我还在Singular Systems 网站上使用商业许可提供了该库。

我有一个占用空间小但非常有能力的数学评估器,它完全不受阻碍。

主要特点

  • 基本数学运算符,具有推断优先级 ( + - * × / ÷ % ^ )。
  • 带括号的显式优先级。
  • 括号内的子表达式的隐式乘法。
  • 修正指数的右结合性(幂运算符)。
  • 直接支持以0x为前缀的十六进制数字。
  • 常量和变量。
  • 可扩展的功能。
  • 可扩展的运算符。
  • 微小的 20 KiB 占用空间。

这是一个简单的例子,它计算文本显示部分的中间列(偏左)。

MathEval            math=new MathEval();

math.setVariable("Top",    5);
math.setVariable("Left",  20);
math.setVariable("Bottom",15);
math.setVariable("Right", 60);

System.out.println("Middle: "+math.evaluate("floor((Right+1-Left)/2)"));                        // 20

我已经在这里发布了类似的答案。 我只想说我一直在开发一个支持数学、布尔值和字符串表达式计算的小库。 这是一个小例子:

String expression = "EXP(var)";
ExpressionEvaluator evaluator = new ExpressionEvaluator();
evaluator.putVariable(new Variable("var", VariableType.NUMBER, new BigDecimal(20)));

System.out.println("Value of exp(var) : " + evaluator.evaluate(expression).getValue());

如果你有兴趣,可以在这里找到

您可以查看ParserNG ,这是一个成熟且速度极快的数学表达式解析器,可在编译-评估阶段工作。 编译阶段解析/理解表达式。 评估阶段解决了这个问题,而且速度非常快。

我称它为解析器,但不仅如此。

它计算数学表达式,支持变量和常量的创建和使用,支持内置和自定义函数的创建,求解二次方程、联立方程、Tartaglia 方程( ax^3+b.x+c=0 ),还求解ax^3+b.x+c=0方程单变量通过迭代方式(使用许多回退技术),进行基本统计,微分(包括它自己的符号微分器的实现,它用于在给定值处吐出导数的数值),解决数值积分。

它还通过 Function 类处理矩阵,并支持使用矩阵函数的各种矩阵运算。

这还不是全部。

作为一个例子,这里是解析器做一些微积分:

MathExpression expr = new MathExpression("f(x)=x^3*ln(x); diff(f,3,1)"); 
System.out.println("result: " + expr.solve());

 result: 38.66253179403897

此 stackoverflow 答案中查看有关它的更多信息

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM