Java: как реализовать разбор математики - PullRequest
1 голос
/ 16 декабря 2010

Я пытаюсь реализовать простой математический парсер в Java.Это для моего небольшого школьного проекта, работающего с матрицами, который позволяет вводить некоторые простые уравнения, такие как A ^ -1 (B + C), а затем программа запрашивает ввод матриц A, B и C и выводит результат для этих операций.

То, что я получил до сих пор, - это класс с именем MathParser, который создает объекты класса Operation.Операция имеет такие методы, как setOperation (один из плюс, время, обратное, мощность) и addInput (Matrix | Operation | int) и, наконец, executeOperation(), который зацикливает все элементы из addInput () и выполняет выбранную операцию из setOperation.Если он обнаруживает, что какой-то элемент из входных данных является экземпляром класса Operation, он сначала выполняет его - это своего рода повторяющийся вызов.Это делается таким образом, чтобы управлять порядком работы - умножение идет до сложения и т. Д.

Однако я не считаю это решение очень хорошим.У вас есть идеи, как реализовать такую ​​задачу?

Ответы [ 7 ]

1 голос
/ 16 декабря 2010

Ну, может быть, это решение не совсем то, что вам нужно / нужно реализовать, или, может быть, это излишнее, но я бы пошел с некоторым скриптовым движком (например Groovy). В таком случае ваш код будет выглядеть так:

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

Кроме того, вы также можете анализировать формулы любой сложности или даже использовать ваши специальные функции расчета. Вы просто помещаете все это в оболочку и затем оцениваете входную строку.

Добавлено: По умолчанию операторы не работают с матрицами, но это не сложно реализовать с помощью 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
1 голос
/ 16 декабря 2010

Я нашел блог, описывающий, как анализировать и выполнять выражения в простом калькуляторе, а затем смотреть на деревья выражений.

Это может быть немного сверху, но должно дать несколько советов:

http://community.bartdesmet.net/blogs/bart/archive/2006/10/11/4513.aspx

0 голосов
/ 22 апреля 2017

Вы можете использовать библиотеку, созданную специально для анализа математических выражений, например 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 и Определение API mXparser .

7 - mXparser поддерживает:

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

С наилучшими пожеланиями

0 голосов
/ 10 марта 2012

Взгляните на http://bracer.sourceforge.net Это моя реализация алгоритма маневрового двора.

0 голосов
/ 23 июля 2011

я выпустил оценщик выражений, основанный на алгоритме Shijnting Yard Дейкстры на условиях Apache License 2.0 :

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

0 голосов
/ 16 декабря 2010

Каноническим методом разбора математических выражений является алгоритм маневрового двора.Это очень простой и элегантный алгоритм, и его реализация многому вас научит.

http://en.wikipedia.org/wiki/Shunting-yard_algorithm имеет хорошее описание, дополненное проработанным примером.

0 голосов
/ 16 декабря 2010

Рассматривали ли вы использование встроенных сценариев?

...