Метод оценки математических выражений в Java - PullRequest
47 голосов
/ 31 августа 2011

В одном из моих проектов я хочу добавить функцию, которую пользователь может предоставить в формуле, например

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
}

Как я могу оценить математические выражения?

Ответы [ 7 ]

22 голосов
/ 15 ноября 2011

Существует также exp4j , оценщик выражений, основанный на Dijkstra's Shunting Yard. Он свободно доступен и распространяется по лицензии Apache License 2.0, его размер составляет всего около 25 КБ, и он довольно прост в использовании:

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 .

8 голосов
/ 20 декабря 2012

Чтобы расширить список, я только что закончил один:

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();
8 голосов
/ 31 августа 2011

Это зависит от того, насколько сложными являются выражения, которые вы хотите оценить, но для простых, 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 );
    }
}
2 голосов
/ 02 июня 2018

Добавив еще одну опцию в список, я написал 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 .

2 голосов
/ 20 апреля 2017

Хороший математический парсер, содержащий обширную математическую коллекцию - 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 .

С уважением

1 голос
/ 06 ноября 2012

У меня небольшая, но очень способная математическая оценка , которая полностью не обременена.

Основные функции

  • Основные математические операторы с предполагаемым приоритетом (+ - * × / ÷ % ^).
  • Явный приоритет с круглыми скобками.
  • Неявное умножение заключенных в скобки подвыражений.
  • Правильная ассоциативность справа экспонент (оператор степени).
  • Прямая поддержка шестнадцатеричных чисел с префиксом 0x.
  • Константы и переменные.
  • Расширяемыйфункции.
  • Расширяемые операторы.
  • Крошечный объем в 20 КиБ.

Вот простой пример, который вычисляет средний столбец подраздела текстового дисплея (смещенный слева).

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
0 голосов
/ 18 июля 2018

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

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());

Если вам интересно, он доступен здесь .

...