评估字符串 "3*(4+2)" 产生 int 18

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/333737/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-03 23:35:09  来源:igfitidea点击:

Evaluating string "3*(4+2)" yield int 18

c#stringmathnumericevaluate

提问by sindre j

Is there a function the .NET framework that can evaluate a numeric expression contained in a string and return the result? F.e.:

.NET 框架中是否有可以计算字符串中包含的数值表达式并返回结果的函数?铁:

string mystring = "3*(2+4)";
int result = EvaluateExpression(mystring);
Console.Writeln(result); // Outputs 18

Is there a standard framework function that you can replace my EvaluateExpressionmethod with?

是否有标准框架功能可以替换我的EvaluateExpression方法?

采纳答案by arul

Yes, you can let C# compiler evaluate it at runtime.

是的,您可以让 C# 编译器在运行时评估它。

See: CSharpCorner

参见:CSharpCorner

回答by Jon Skeet

You could fairly easily run this through the CSharpCodeProvider with suitable fluff wrapping it (a type and a method, basically). Likewise you could go through VB etc - or JavaScript, as another answer has suggested. I don't know of anything else built into the framework at this point.

你可以很容易地通过 CSharpCodeProvider 运行它,并用合适的绒毛包裹它(基本上是一种类型和一种方法)。同样,您可以通过 VB 等 - 或 JavaScript,正如另一个答案所建议的那样。在这一点上,我不知道框架中内置了任何其他内容。

I'd expect that .NET 4.0 with its support for dynamic languages may well have better capabilities on this front.

我希望支持动态语言的 .NET 4.0 在这方面具有更好的功能。

回答by arul

Short answer: I don't think so. C# .Net is compiled (to bytecode) and can't evaluate strings at runtime, as far as I know. JScript .Net can, however; but I would still advise you to code a parser and stack-based evaluator yourself.

简短的回答:我不这么认为。据我所知,C# .Net 被编译(到字节码)并且不能在运行时评估字符串。然而,JScript .Net 可以;但我仍然建议您自己编写解析器和基于堆栈的评估器。

回答by Tamas Czinege

There is not. You will need to use some external library, or write your own parser. If you have the time to do so, I suggest to write your own parser as it is a quite interesting project. Otherwise you will need to use something like bcParser.

那没有。您将需要使用一些外部库,或编写自己的解析器。如果您有时间这样做,我建议您编写自己的解析器,因为这是一个非常有趣的项目。否则,您将需要使用类似bcParser 的东西。

回答by Beardo

I recently needed to do this for a project and I ended up using IronPythonto do it. You can declare an instance of the engine, and then pass any valid python expression and get the result. If you're just doing simple math expressions, then it would suffice. My code ended up looking similar to:

我最近需要为一个项目执行此操作,最终我使用IronPython来执行此操作。您可以声明引擎的一个实例,然后传递任何有效的python 表达式并获取结果。如果你只是做简单的数学表达式,那么就足够了。我的代码最终看起来类似于:

IronPython.Hosting.PythonEngine pythonEngine = new IronPython.Hosting.PythonEngine();
string expression = "3*(2+4)";
double result = pythonEngine.EvaluateAs<double>(expression);

You'd probably not want to create the engine for each expression. You also need a reference to IronPython.dll

您可能不想为每个表达式创建引擎。您还需要对 IronPython.dll 的引用

回答by Olav Botterli

You could look at "XpathNavigator.Evaluate" I have used this to process mathematical expressions for my GridView and it works fine for me.

你可以看看“XpathNavigator.Evaluate”我用它来处理我的 GridView 的数学表达式,它对我来说很好用。

Here is the code I used for my program:

这是我用于我的程序的代码:

public static double Evaluate(string expression)
{
    return (double)new System.Xml.XPath.XPathDocument
    (new StringReader("<r/>")).CreateNavigator().Evaluate
    (string.Format("number({0})", new
    System.Text.RegularExpressions.Regex(@"([\+\-\*])")
    .Replace(expression, "  ")
    .Replace("/", " div ")
    .Replace("%", " mod ")));
}

回答by pero

Try this:

尝试这个:

static double Evaluate(string expression) {
  var loDataTable = new DataTable();
  var loDataColumn = new DataColumn("Eval", typeof (double), expression);
  loDataTable.Columns.Add(loDataColumn);
  loDataTable.Rows.Add(0);
  return (double) (loDataTable.Rows[0]["Eval"]);
}

回答by Sébastien Ros - MSFT

Using the compiler to do implies memory leaks as the generated assemblies are loaded and never released. It's also less performant than using a real expression interpreter. For this purpose you can use Ncalcwhich is an open-source framework with this solely intent. You can also define your own variables and custom functions if the ones already included aren't enough.

使用编译器来做意味着内存泄漏,因为生成的程序集被加载并且永远不会被释放。它的性能也低于使用真正的表达式解释器。为此,您可以使用Ncalc,它是一个完全出于此目的的开源框架。如果已经包含的变量和自定义函数不够用,您还可以定义自己的变量和自定义函数。

Example:

例子:

Expression e = new Expression("2 + 3 * 5");
Debug.Assert(17 == e.Evaluate());

回答by Tawani

This is a simple Expression Evaluator using Stacks

这是一个使用 Stacks 的简单表达式评估器

public class MathEvaluator
{
    public static void Run()
    {
        Eval("(1+2)");
        Eval("5*4/2");
        Eval("((3+5)-6)");
    }

    public static void Eval(string input)
    {
        var ans = Evaluate(input);
        Console.WriteLine(input + " = " + ans);
    }

    public static double Evaluate(String input)
    {
        String expr = "(" + input + ")";
        Stack<String> ops = new Stack<String>();
        Stack<Double> vals = new Stack<Double>();

        for (int i = 0; i < expr.Length; i++)
        {
            String s = expr.Substring(i, 1);
            if (s.Equals("(")){}
            else if (s.Equals("+")) ops.Push(s);
            else if (s.Equals("-")) ops.Push(s);
            else if (s.Equals("*")) ops.Push(s);
            else if (s.Equals("/")) ops.Push(s);
            else if (s.Equals("sqrt")) ops.Push(s);
            else if (s.Equals(")"))
            {
                int count = ops.Count;
                while (count > 0)
                {
                    String op = ops.Pop();
                    double v = vals.Pop();
                    if (op.Equals("+")) v = vals.Pop() + v;
                    else if (op.Equals("-")) v = vals.Pop() - v;
                    else if (op.Equals("*")) v = vals.Pop()*v;
                    else if (op.Equals("/")) v = vals.Pop()/v;
                    else if (op.Equals("sqrt")) v = Math.Sqrt(v);
                    vals.Push(v);

                    count--;
                }
            }
            else vals.Push(Double.Parse(s));
        }
        return vals.Pop();
    }
}

回答by Rajesh Jinaga

This is right to left execution, so need to use proper parathesis to execute expression

这是从右到左的执行,因此需要使用适当的插补来执行表达式

    // 2+(100/5)+10 = 32
    //((2.5+10)/5)+2.5 = 5
    // (2.5+10)/5+2.5 = 1.6666
    public static double Evaluate(String expr)
    {

        Stack<String> stack = new Stack<String>();

        string value = "";
        for (int i = 0; i < expr.Length; i++)
        {
            String s = expr.Substring(i, 1);
            char chr = s.ToCharArray()[0];

            if (!char.IsDigit(chr) && chr != '.' && value != "")
            {
                stack.Push(value);
                value = "";
            }

            if (s.Equals("(")) {

                string innerExp = "";
                i++; //Fetch Next Character
                int bracketCount=0;
                for (; i < expr.Length; i++)
                {
                    s = expr.Substring(i, 1);

                    if (s.Equals("("))
                        bracketCount++;

                    if (s.Equals(")"))
                        if (bracketCount == 0)
                            break;
                        else
                            bracketCount--;


                    innerExp += s;
                }

                stack.Push(Evaluate(innerExp).ToString());

            }
            else if (s.Equals("+")) stack.Push(s);
            else if (s.Equals("-")) stack.Push(s);
            else if (s.Equals("*")) stack.Push(s);
            else if (s.Equals("/")) stack.Push(s);
            else if (s.Equals("sqrt")) stack.Push(s);
            else if (s.Equals(")"))
            {
            }
            else if (char.IsDigit(chr) || chr == '.')
            {
                value += s;

                if (value.Split('.').Length > 2)
                    throw new Exception("Invalid decimal.");

                if (i == (expr.Length - 1))
                    stack.Push(value);

            }
            else
                throw new Exception("Invalid character.");

        }


        double result = 0;
        while (stack.Count >= 3)
        {

            double right = Convert.ToDouble(stack.Pop());
            string op = stack.Pop();
            double left = Convert.ToDouble(stack.Pop());

            if (op == "+") result = left + right;
            else if (op == "+") result = left + right;
            else if (op == "-") result = left - right;
            else if (op == "*") result = left * right;
            else if (op == "/") result = left / right;

            stack.Push(result.ToString());
        }


        return Convert.ToDouble(stack.Pop());
    }