java:如何实现数学解析

发布于 2024-10-07 22:19:21 字数 472 浏览 3 评论 0原文

我正在尝试用java实现一个简单的数学解析器。这是针对我的小型学校项目,该项目使用矩阵,可以输入一些简单的方程,例如 A^-1(B+C),然后程序要求输入矩阵 A、B 和 C 并输出这些运算的结果。

到目前为止我得到的是一个名为MathParser 的类,它创建Operation 类的对象。 Operation 具有诸如 setOperation(plus、times、inverse、power 之一)和 addInput(Matrix|Operation|int) 等方法,最后是 executeOperation() 循环 addInput() 中的所有项目并执行 setOperation 中选定的操作。如果它发现输入中的某些项目是类操作的实例,它首先执行它 - 这是一种循环调用。它是通过这种方式来管理运算顺序的 - 乘法先于加法等。

但是,我认为这个解决方案不是很好。您对如何执行这样的任务有什么想法吗?

I am trying to implement a simple math parser in java. This is for my small school project working with matrices that enables to input some simple equations, such as A^-1(B+C) and then the program asks to input matrices A,B and C and outputs result for these operations.

What I got so far is a class called MathParser, that creates objects of class Operation.
Operation has methods like setOperation ( one of plus,times,inverse,power) and addInput(Matrix|Operation|int) and finally executeOperation() that loops all items from addInput() and executes chosen operation from setOperation. If it finds that some item from the input is instance of class Operation, it executes it first - this is a sort of recurrent calling. It is done this way to manage operation order - multiplying comes before addition etc.

However, I don't find this solution very good. Do you have any ideas how to implement such a task?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

老街孤人 2024-10-14 22:19:26

您可以考虑使用专门为数学表达式解析构建的库,例如mXparser。您将获得许多非常有用的选项:

1 - 检查表达式语法

import org.mariuszgromada.math.mxparser.*;
...
...
Expression e = new Expression("2+3-");
e.checkSyntax();
mXparser.consolePrintln(e.getErrorMessage());

结果:

[mXparser-v.4.0.0] [2+3-] checking ...
[2+3-] lexical error 

Encountered "<EOF>" at line 1, column 4.
Was expecting one of:
    "(" ...
    "+" ...
    "-" ...
    <UNIT> ...
    "~" ...
    "@~" ...
    <NUMBER_CONSTANT> ...
    <IDENTIFIER> ...
    <FUNCTION> ...
    "[" ...

[2+3-] errors were found.

[mXparser-v.4.0.0]

2 - 评估表达式

import org.mariuszgromada.math.mxparser.*;
...
...
Expression e = new Expression("2+3-(10+2)");
mXparser.consolePrintln(e.getExpressionString() + " = " + e.calculate());

结果:

[mXparser-v.4.0.0] 2+3-(10+2) = -7.0

3 - 使用内置函数常量、运算符等。

import org.mariuszgromada.math.mxparser.*;
...
...
Expression e = new Expression("sin(pi)+e");
mXparser.consolePrintln(e.getExpressionString() + " = " + e.calculate());

结果:

[mXparser-v.4.0.0] sin(pi)+e = 2.718281828459045

4 - 定义自己的函数、参数和常量

import org.mariuszgromada.math.mxparser.*;
...
...
Argument z = new Argument("z = 10");
Constant a = new Constant("b = 2");
Function p = new Function("p(a,h) = a*h/2");
Expression e = new Expression("p(10, 2)-z*b/2", p, z, a);
mXparser.consolePrintln(e.getExpressionString() + " = " + e.calculate());

结果:

[mXparser-v.4.0.0] p(10, 2)-z*b/2 = 0.0

5 - 标记表达式字符串并使用表达式标记

import org.mariuszgromada.math.mxparser.*;
...
...
Argument x = new Argument("x");
Argument y = new Argument("y");
Expression e = new Expression("2*sin(x)+(3/cos(y)-e^(sin(x)+y))+10", x, y);
mXparser.consolePrintTokens( e.getCopyOfInitialTokens() );

结果:

[mXparser-v.4.0.0]  --------------------
[mXparser-v.4.0.0] | Expression tokens: |
[mXparser-v.4.0.0]  ---------------------------------------------------------------------------------------------------------------
[mXparser-v.4.0.0] |    TokenIdx |       Token |        KeyW |     TokenId | TokenTypeId |  TokenLevel |  TokenValue |   LooksLike |
[mXparser-v.4.0.0]  ---------------------------------------------------------------------------------------------------------------
[mXparser-v.4.0.0] |           0 |           2 |       _num_ |           1 |           0 |           0 |         2.0 |             |
[mXparser-v.4.0.0] |           1 |           * |           * |           3 |           1 |           0 |         NaN |             |
[mXparser-v.4.0.0] |           2 |         sin |         sin |           1 |           4 |           1 |         NaN |             |
[mXparser-v.4.0.0] |           3 |           ( |           ( |           1 |          20 |           2 |         NaN |             |
[mXparser-v.4.0.0] |           4 |           x |           x |           0 |         101 |           2 |         NaN |             |
[mXparser-v.4.0.0] |           5 |           ) |           ) |           2 |          20 |           2 |         NaN |             |
[mXparser-v.4.0.0] |           6 |           + |           + |           1 |           1 |           0 |         NaN |             |
[mXparser-v.4.0.0] |           7 |           ( |           ( |           1 |          20 |           1 |         NaN |             |
[mXparser-v.4.0.0] |           8 |           3 |       _num_ |           1 |           0 |           1 |         3.0 |             |
[mXparser-v.4.0.0] |           9 |           / |           / |           4 |           1 |           1 |         NaN |             |
[mXparser-v.4.0.0] |          10 |         cos |         cos |           2 |           4 |           2 |         NaN |             |
[mXparser-v.4.0.0] |          11 |           ( |           ( |           1 |          20 |           3 |         NaN |             |
[mXparser-v.4.0.0] |          12 |           y |           y |           1 |         101 |           3 |         NaN |             |
[mXparser-v.4.0.0] |          13 |           ) |           ) |           2 |          20 |           3 |         NaN |             |
[mXparser-v.4.0.0] |          14 |           - |           - |           2 |           1 |           1 |         NaN |             |
[mXparser-v.4.0.0] |          15 |           e |           e |           2 |           9 |           1 |         NaN |             |
[mXparser-v.4.0.0] |          16 |           ^ |           ^ |           5 |           1 |           1 |         NaN |             |
[mXparser-v.4.0.0] |          17 |           ( |           ( |           1 |          20 |           2 |         NaN |             |
[mXparser-v.4.0.0] |          18 |         sin |         sin |           1 |           4 |           3 |         NaN |             |
[mXparser-v.4.0.0] |          19 |           ( |           ( |           1 |          20 |           4 |         NaN |             |
[mXparser-v.4.0.0] |          20 |           x |           x |           0 |         101 |           4 |         NaN |             |
[mXparser-v.4.0.0] |          21 |           ) |           ) |           2 |          20 |           4 |         NaN |             |
[mXparser-v.4.0.0] |          22 |           + |           + |           1 |           1 |           2 |         NaN |             |
[mXparser-v.4.0.0] |          23 |           y |           y |           1 |         101 |           2 |         NaN |             |
[mXparser-v.4.0.0] |          24 |           ) |           ) |           2 |          20 |           2 |         NaN |             |
[mXparser-v.4.0.0] |          25 |           ) |           ) |           2 |          20 |           1 |         NaN |             |
[mXparser-v.4.0.0] |          26 |           + |           + |           1 |           1 |           0 |         NaN |             |
[mXparser-v.4.0.0] |          27 |          10 |       _num_ |           1 |           0 |           0 |        10.0 |             |
[mXparser-v.4.0.0]  ---------------------------------------------------------------------------------------------------------------

6 - 同样重要的是 - 您会在中找到更多内容 mXparser 教程mXparser 数学集合mXparser API 定义

7 - mXparser 支持:

  • JAVA
  • .NET/MONO
  • .NET Core
  • .NET Standard
  • .NET PCL
  • Xamarin.Android
  • Xamarin.iOS

谨致问候

You can consider using library built specifically for math expression parsing, such as mXparser. You will get a lot of very helpful options:

1 - Checking expression syntax

import org.mariuszgromada.math.mxparser.*;
...
...
Expression e = new Expression("2+3-");
e.checkSyntax();
mXparser.consolePrintln(e.getErrorMessage());

Result:

[mXparser-v.4.0.0] [2+3-] checking ...
[2+3-] lexical error 

Encountered "<EOF>" at line 1, column 4.
Was expecting one of:
    "(" ...
    "+" ...
    "-" ...
    <UNIT> ...
    "~" ...
    "@~" ...
    <NUMBER_CONSTANT> ...
    <IDENTIFIER> ...
    <FUNCTION> ...
    "[" ...

[2+3-] errors were found.

[mXparser-v.4.0.0]

2 - Evaluating expression

import org.mariuszgromada.math.mxparser.*;
...
...
Expression e = new Expression("2+3-(10+2)");
mXparser.consolePrintln(e.getExpressionString() + " = " + e.calculate());

Result:

[mXparser-v.4.0.0] 2+3-(10+2) = -7.0

3 - Using built-in functions constants, operators, etc..

import org.mariuszgromada.math.mxparser.*;
...
...
Expression e = new Expression("sin(pi)+e");
mXparser.consolePrintln(e.getExpressionString() + " = " + e.calculate());

Result:

[mXparser-v.4.0.0] sin(pi)+e = 2.718281828459045

4 - Defining your own functions, arguments and constants

import org.mariuszgromada.math.mxparser.*;
...
...
Argument z = new Argument("z = 10");
Constant a = new Constant("b = 2");
Function p = new Function("p(a,h) = a*h/2");
Expression e = new Expression("p(10, 2)-z*b/2", p, z, a);
mXparser.consolePrintln(e.getExpressionString() + " = " + e.calculate());

Result:

[mXparser-v.4.0.0] p(10, 2)-z*b/2 = 0.0

5 - Tokenizing expression string and playing with expression tokens

import org.mariuszgromada.math.mxparser.*;
...
...
Argument x = new Argument("x");
Argument y = new Argument("y");
Expression e = new Expression("2*sin(x)+(3/cos(y)-e^(sin(x)+y))+10", x, y);
mXparser.consolePrintTokens( e.getCopyOfInitialTokens() );

Result:

[mXparser-v.4.0.0]  --------------------
[mXparser-v.4.0.0] | Expression tokens: |
[mXparser-v.4.0.0]  ---------------------------------------------------------------------------------------------------------------
[mXparser-v.4.0.0] |    TokenIdx |       Token |        KeyW |     TokenId | TokenTypeId |  TokenLevel |  TokenValue |   LooksLike |
[mXparser-v.4.0.0]  ---------------------------------------------------------------------------------------------------------------
[mXparser-v.4.0.0] |           0 |           2 |       _num_ |           1 |           0 |           0 |         2.0 |             |
[mXparser-v.4.0.0] |           1 |           * |           * |           3 |           1 |           0 |         NaN |             |
[mXparser-v.4.0.0] |           2 |         sin |         sin |           1 |           4 |           1 |         NaN |             |
[mXparser-v.4.0.0] |           3 |           ( |           ( |           1 |          20 |           2 |         NaN |             |
[mXparser-v.4.0.0] |           4 |           x |           x |           0 |         101 |           2 |         NaN |             |
[mXparser-v.4.0.0] |           5 |           ) |           ) |           2 |          20 |           2 |         NaN |             |
[mXparser-v.4.0.0] |           6 |           + |           + |           1 |           1 |           0 |         NaN |             |
[mXparser-v.4.0.0] |           7 |           ( |           ( |           1 |          20 |           1 |         NaN |             |
[mXparser-v.4.0.0] |           8 |           3 |       _num_ |           1 |           0 |           1 |         3.0 |             |
[mXparser-v.4.0.0] |           9 |           / |           / |           4 |           1 |           1 |         NaN |             |
[mXparser-v.4.0.0] |          10 |         cos |         cos |           2 |           4 |           2 |         NaN |             |
[mXparser-v.4.0.0] |          11 |           ( |           ( |           1 |          20 |           3 |         NaN |             |
[mXparser-v.4.0.0] |          12 |           y |           y |           1 |         101 |           3 |         NaN |             |
[mXparser-v.4.0.0] |          13 |           ) |           ) |           2 |          20 |           3 |         NaN |             |
[mXparser-v.4.0.0] |          14 |           - |           - |           2 |           1 |           1 |         NaN |             |
[mXparser-v.4.0.0] |          15 |           e |           e |           2 |           9 |           1 |         NaN |             |
[mXparser-v.4.0.0] |          16 |           ^ |           ^ |           5 |           1 |           1 |         NaN |             |
[mXparser-v.4.0.0] |          17 |           ( |           ( |           1 |          20 |           2 |         NaN |             |
[mXparser-v.4.0.0] |          18 |         sin |         sin |           1 |           4 |           3 |         NaN |             |
[mXparser-v.4.0.0] |          19 |           ( |           ( |           1 |          20 |           4 |         NaN |             |
[mXparser-v.4.0.0] |          20 |           x |           x |           0 |         101 |           4 |         NaN |             |
[mXparser-v.4.0.0] |          21 |           ) |           ) |           2 |          20 |           4 |         NaN |             |
[mXparser-v.4.0.0] |          22 |           + |           + |           1 |           1 |           2 |         NaN |             |
[mXparser-v.4.0.0] |          23 |           y |           y |           1 |         101 |           2 |         NaN |             |
[mXparser-v.4.0.0] |          24 |           ) |           ) |           2 |          20 |           2 |         NaN |             |
[mXparser-v.4.0.0] |          25 |           ) |           ) |           2 |          20 |           1 |         NaN |             |
[mXparser-v.4.0.0] |          26 |           + |           + |           1 |           1 |           0 |         NaN |             |
[mXparser-v.4.0.0] |          27 |          10 |       _num_ |           1 |           0 |           0 |        10.0 |             |
[mXparser-v.4.0.0]  ---------------------------------------------------------------------------------------------------------------

6 - Whats equally important - you will find much more in mXparser tutorial, mXparser math collection and mXparser API definition.

7 - mXparser supports:

  • JAVA
  • .NET/MONO
  • .NET Core
  • .NET Standard
  • .NET PCL
  • Xamarin.Android
  • Xamarin.iOS

Best regards

千笙结 2024-10-14 22:19:25

我根据 Dijkstra 的 Shunting Yard 算法发布了一个表达式求值器,遵循 Apache 许可证 2.0

http://projects.congrace.de/exp4j/index.html

i released an expression evaluator based on Dijkstra's Shunting Yard algorithm, under the terms of the Apache License 2.0:

http://projects.congrace.de/exp4j/index.html

≈。彩虹 2024-10-14 22:19:25

看看 http://bracer.sourceforge.net 这是我对调车场算法的实现。

Have a look at http://bracer.sourceforge.net It's my implementation of shunting-yard algorithm.

未央 2024-10-14 22:19:24

您是否考虑过使用嵌入式脚本?

Have you considered using embedded scripting?

左耳近心 2024-10-14 22:19:23

好吧,也许这个解决方案并不完全是您需要/想要实现的,或者可能是一种矫枉过正,但我​​会使用一些脚本引擎(例如 Groovy)。在这种情况下,您的代码将如下所示:

GroovyShell shell = new GroovyShell();
shell.setVariable("a",10);
shell.setVariable("b",20);
int result = ((Number) shell.evaluate("(a+b)/2")).intValue();

此外,您还可以解析任何复杂性的公式,甚至使用特定的计算函数。您只需将其全部放入 shell 中,然后评估输入字符串即可。

添加:
默认情况下,运算符不处理矩阵,但使用 groovy 实现它并不难,因为它支持运算符重载(在此处了解更多信息:http://groovy.codehaus.org/Operator+Overloading

这是一个矩阵示例:

class Matrix {
    private int[][] data;

    public Matrix(int[][] data) {
        this.data = data;
    }

    public int[][] getData() {
        return data;
    }

    //Method that overloads the groovy '+' operator
    public Matrix plus(Matrix b) {
        Matrix result = calculateMatrixSumSomehow(this,b);
        return result;
    }
}

现在您的调用将如下所示:

shell.setVariable("A",new Matrix(...));
shell.setVariable("B",new Matrix(...));
Matrix result = (Matrix)shell.evaluate("A+B"); //+ operator will use 'plus' function

Well, maybe this solution is not exactly what you need/want to implement or maybe it's a overkill, but I'd go with some scripting engine (for example Groovy). In that case this is how your code would look:

GroovyShell shell = new GroovyShell();
shell.setVariable("a",10);
shell.setVariable("b",20);
int result = ((Number) shell.evaluate("(a+b)/2")).intValue();

Moreover, you can also parse formulas of any complexity or even using your specific calculation functions. You just put it all into the shell and then evaluate the input string.

Added:
Operators do not work with matrices by default, but it is not hard to implement that with groovy as it supports operator overloading (read more about it here: http://groovy.codehaus.org/Operator+Overloading)

So here is an example with matrices:

class Matrix {
    private int[][] data;

    public Matrix(int[][] data) {
        this.data = data;
    }

    public int[][] getData() {
        return data;
    }

    //Method that overloads the groovy '+' operator
    public Matrix plus(Matrix b) {
        Matrix result = calculateMatrixSumSomehow(this,b);
        return result;
    }
}

Now in your call will look like this:

shell.setVariable("A",new Matrix(...));
shell.setVariable("B",new Matrix(...));
Matrix result = (Matrix)shell.evaluate("A+B"); //+ operator will use 'plus' function
稀香 2024-10-14 22:19:23

解析数学表达式的规范方法是调车场算法。这是一个非常简单而优雅的算法,实现它会教会你很多东西。

http://en.wikipedia.org/wiki/Shunting-yard_algorithm有很好的描述,并附有一个工作示例。

The canonical method for parsing mathematical expressions is the shunting yard algorithm. It is a very simple and elegant algorithm, and implementing it will teach you a lot.

http://en.wikipedia.org/wiki/Shunting-yard_algorithm has a good description, complete with a worked example.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文