Разбора Математических Выражений

есть ли простой способ проанализировать простое математическое выражение, представленное в виде строки, такой как (x+(2*x)/(1-x)), предоставить значение для x и получить результат?

Я посмотрел на VSAEngine за несколько онлайн-примеров, однако я получаю предупреждение о том, что эта сборка устарела и не использовать ее.

Если это имеет значение, я использую .NET 4.0.

9 ответов


вы можете попробовать использовать DataTable.Вычислить.

связанный является объект datacolumn.Выражение.

также проверьте:делать математику в vb.net как Eval в javascript

примечание: Я не использовал их сам.


Я призываю к осторожности при выборе существующего универсального оценщика выражений над специально построенным математическим оценщиком. Причина этого заключается в том, что оценщики выражений не ограничиваются только математикой. Умный человек мог бы использовать это, чтобы создать экземпляр любого типа в рамках и вызвать любой метод на типе, и это позволило бы ему делать некоторые решительно нежелательные вещи. Например: new System.Net.WebClient().DownloadFile("illegalchildpornurl", "C:\openme.gif") будет оценивать просто отлично в большинстве из них, и делать только то, что это звучит так (и в то же время сделать вас преступником).

Это не значит, что не ищите то, что уже написано. Просто будь осторожен. Вам нужен тот, кто занимается математикой, и только математикой. Большая часть того, что уже есть, не настолько разборчива.


недавно я использовал mXparser, который является библиотекой математического анализатора. Это дает вам большую гибкость, такие как переменные, функции, константы, операторы. Ниже вы найдете несколько примеров использования:

Пример 1 - Простая формула

Expression e = new Expression("1 + pi");
double v = e.calculate();

Пример 2 - формулы с переменными, функциями и т. д.

Argument x = new Argument("x = 2");
Constant a = new Constant("a = sin(10)");
Function f = new Function("f(t) = t^2");
Expression e = new Expression("2*x + a - f(10)", x, a, f);
double v = e.calculate();

https://mxparser.codeplex.com/

http://mathparser.org/

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


Я бы также посмотрел на Джейса (https://github.com/pieterderycke/Jace). Jace-высокопроизводительный математический парсер и вычислительный движок, который поддерживает все .NET-вкусы (.NET 4.x, Windows Phone, Магазин Windows,...). Джейс также доступен через NuGet: https://www.nuget.org/packages/Jace


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

public class ExpressionParser {
public double eval(String exp, Map<String, Double> vars){
    int bracketCounter = 0;
    int operatorIndex = -1;

    for(int i=0; i<exp.length(); i++){
        char c = exp.charAt(i);
        if(c == '(') bracketCounter++;
        else if(c == ')') bracketCounter--;
        else if((c == '+' || c == '-') && bracketCounter == 0){
            operatorIndex = i;
            break;
        }
        else if((c == '*' || c == '/') && bracketCounter == 0 && operatorIndex < 0){
            operatorIndex = i;
        }
    }
    if(operatorIndex < 0){
        exp = exp.trim();
        if(exp.charAt(0) == '(' && exp.charAt(exp.length()-1) == ')')
            return eval(exp.substring(1, exp.length()-1), vars);
        else if(vars.containsKey(exp))
            return vars.get(exp);
        else
            return Double.parseDouble(exp);
    }
    else{
        switch(exp.charAt(operatorIndex)){
            case '+':
                return eval(exp.substring(0, operatorIndex), vars) + eval(exp.substring(operatorIndex+1), vars);
            case '-':
                return eval(exp.substring(0, operatorIndex), vars) - eval(exp.substring(operatorIndex+1), vars);
            case '*':
                return eval(exp.substring(0, operatorIndex), vars) * eval(exp.substring(operatorIndex+1), vars);
            case '/':
                return eval(exp.substring(0, operatorIndex), vars) / eval(exp.substring(operatorIndex+1), vars);
        }
    }
    return 0;
}

}

вам нужно импортировать java.утиль.Карта.

вот как я использую этот код:

    ExpressionParser p = new ExpressionParser();
    Map vars = new HashMap<String, Double>();
    vars.put("x", 2.50);
    System.out.println(p.eval(" 5 + 6 * x - 1", vars));

другой вариант, который вы можете захотеть изучить, это Spring.NET фреймворк выражения функциональность. Он может делать гораздо больше, чем математику.

однако, весь Spring.NET Framework может быть немного излишним для ваших нужд, если вам не требуется остальная функциональность.



Как я ответил в этой теме (лучший бесплатный C# Math Parser с использованием переменных, пользовательских функций, пользовательских операторов), вы можете использовать Mathos Parser, который вы можете просто вставить в свой исходный код.

        Mathos.Parser.MathParser parser = new Mathos.Parser.MathParser();

        string expr = "(x+(2*x)/(1-x))"; // the expression

        decimal result = 0; // the storage of the result

        parser.LocalVariables.Add("x", 41); // 41 is the value of x

        result = parser.Parse(expr); // parsing

        Console.WriteLine(result); // 38.95

Я рекомендую вам использовать MEEL для этого.

// parse string to IExpression (symbolic type)
IExpression expression = BaseExpression.Parse("(x+(2*x)/(1-x))");

// create your own collection for attributes
var attributes = new MathAttributeCollection();
// create local variable named "x" with value 5
var attributeX = new ScalarAttrInt("x") {Value = new ScalarConstInt(5)};
attributes.Add(attributeX);

// execute math expression where x=5
var result = expression.Execute(attributes);

MessageBox.Show(result.GetText());
// result: 2.5