解析数学表达式

16

有没有一种简单的方法来解析代表数学表达式的字符串(例如(x+(2*x)/(1-x))并为x提供一个值并得到结果?

我看了几个在线示例使用VSAEngine,但是我收到了一个警告,说明此程序集已被弃用,请勿再使用。

如果有任何区别的话,我正在使用.NET 4.0。


我在这里发布了这个问题的完整源代码:https://dev59.com/OnVC5IYBdhLWcg3w0EsD - Austin Salonen
9个回答

20

我建议谨慎选择现有的通用表达式求值器而不是专为数学设计的求值器。原因在于,表达式求值器不仅限于数学。聪明的人可以使用它来创建框架中任何类型的实例,并调用类型上的任何方法,这将允许他做一些绝对不受欢迎的事情。例如:new System.Net.WebClient().DownloadFile("illegalchildpornurl", "C:\openme.gif") 在大多数表达式求值器中都可以正常计算,而且会像它听起来的那样执行(同时使您成为重罪犯)。

这并不意味着不要寻找已经编写好的代码;它只是意味着要小心。您需要的是一个只进行数学计算的求值器。而大多数现有的求值器并没有那么挑剔。


6
那个例子有点过分了,你本可以写成 "illegalurl"。 - Zimano

13

我最近使用了一个叫做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/

https://mathparser.org/

最近发现 - 您可以通过由mXparser提供支持的Scalar Calculator app尝试语法(并查看用例)。
最好的问候

8

由于我没有进行任何三角函数计算(只是简单的数学运算),所以使用 DataTable.Compute 选项是最容易实现的。 - Brandon

3

3

以下是一种实现方式,这段代码使用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.util.Map。

以下是我使用此代码的方法:

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

1
这是一段优美的代码。谢谢。 - Illishar
谢谢 @Illishar - user4617883

1

在这个帖子中,我回答了(使用变量、用户定义函数和自定义运算符的最佳免费C#数学解析器),你可以使用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

很遗憾,这个项目托管在即将关闭的Codeplex上。我现在甚至无法查看Codeplex上的源代码。如果该项目能够重新托管在Github或Bitbucket等网站上,那就太好了。 - Nic Foster
@NicFoster,请查看https://github.com/MathosProject/Mathos-Parser。还有其他版本可在https://github.com/MathosProject找到。 - Artem

1

你可能想要考虑的另一个选项是Spring.NET框架的表达式求值功能。它不仅可以处理数学运算,还可以做很多其他事情。

然而,如果你不需要其余的功能,整个Spring.NET框架可能有点过度。



0

我建议您使用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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接