这个问题已经有一个答案在这里:

是否有一个功能。净框架,可以评估的一个数值的表达载于a string和返回的结果?F.e:

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

是否有一个标准框架的功能,你可以取代我 EvaluateExpression 方法?

有帮助吗?

解决方案

是的,你可以让我们C#compiler评估它在运行时间。

参见: CSharpCorner

其他提示

如果你想要评估串表情使用以下代码段。

using System.Data;

DataTable dt = new DataTable();
var v = dt.Compute("3 * (2+4)","");

使用的编译器做意味着内存泄漏,为所产生的组件装载并永远不会被释放。它也较少的性能比使用一个真正表达的解释。为此目的可以使用 Ncalc 这是一个开放源框架,这仅仅是意图。你也可以定义自己的变量和自定义功能,如果那些已经包括在内是不够的。

例如:

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

试试这个:

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"]);
}

你可以看看在"XpathNavigator.评估"我用这个来处理的数学表达我内,它工作正常对我来说。

这里是代码,我在使用我的程序:

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, " ${1} ")
    .Replace("/", " div ")
    .Replace("%", " mod ")));
}
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"]); 
} 

解释它是如何工作:

首先,我们做个表中的一部分 var loDataTable = new DataTable();, 就像在一个数据库引擎(MS SQL为例)。

然后,一个列有一些具体参数(var loDataColumn = new DataColumn("Eval", typeof (double), expression);).

"Eval" 参数列名(列名属性)。

typeof (double) 是的数据类型将存储在列,这等于把 System.Type.GetType("System.Double"); 代替。

expression 是的字符串 Evaluate 方法接收和储存的属性 Expression 列。这个属性,是一个非常具体的目(显而易见的),它是每一个排,把在列将完成具有"表达",并接受几乎wathever可以放在一个SQL Query.请参阅 http://msdn.microsoft.com/en-us/library/system.data.datacolumn.expression(v=与100).aspx 知道什么可以放在中表达的属性,以及它是如何进行评价。

然后, loDataTable.Columns.Add(loDataColumn); 增列 loDataColumn 来的 loDataTable 表。

然后,一排表中添加一个列有表达的属性,通过 loDataTable.Rows.Add(0);.当我们加入这一行时,该电池的列"Eval"的表 loDataTable 是完成自动与其"表达"的属性,并且,如果已经营者和SQL查询,等等,这是进行评估,然后储存的细胞,因此,这里发生的"魔法",串与运营商进行评估和储存细胞...

最后,刚刚返回的价值储存的细胞柱"Eval"在行0(这是一个指数,开始计数从零),并作出转换到一个双人间 return (double) (loDataTable.Rows[0]["Eval"]);.

和这一切...完成工作!

和这里的代码加方便于理解,它不一样的...这不是内部一个方法,它的解释。

DataTable MyTable = new DataTable();
DataColumn MyColumn = new DataColumn();
MyColumn.ColumnName = "MyColumn";
MyColumn.Expression = "5+5/5"
MyColumn.DataType = typeof(double);
MyTable.Columns.Add(MyColumn);
DataRow MyRow = MyTable.NewRow();
MyTable.Rows.Add(MyRow);
return (double)(MyTable.Rows[0]["MyColumn"]);

第一,创建表 DataTable MyTable = new DataTable();

然后,列 DataColumn MyColumn = new DataColumn();

接下来,我们把名字放到列。这使我们可以搜索进入它的内容时,它是存表。做过 MyColumn.ColumnName = "MyColumn";

然后,表达,这里我们可以把一个可变的种类型字符串,在这种情况下有一串预先定义的"5+5月5日",其结果是6。

这种类型的数据存储列 MyColumn.DataType = typeof(double);

添加的列表... MyTable.Columns.Add(MyColumn);

做一个行为可插入表中,其副本表结构 DataRow MyRow = MyTable.NewRow();

添加行表 MyTable.Rows.Add(MyRow);

和返回单元的值在0行列 MyColumnMyTablereturn (double)(MyTable.Rows[0]["MyColumn"]);

课做!!!

这是一个简单的表达的评估程序采用栈

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

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

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

你可以相当容易地运行这个过CSharpCodeProvider与适当的绒毛包(一种类型和方法,基本上).同样,你可以去通过VB等或JavaScript,作为另一个的回答已经提出了建议。我不知道什么建成的框架,在这一点上。

我期望。净4.0其支持为动态语言可能有更好的能力,在这方面的。

最近,我需要做到这一点的一个项目,和我结束了使用 IronPython 做到这一点。你可以声明的一个实例引擎,然后通过的任何有效的python表达并得到的结果。如果你只是在做一个简单的数学表达,那么这就足够了。我的代码最终寻找类似的:

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

你可能不想要创造的发动机为每个表达。你还需要一个参考IronPython.dll

编辑: 意识到我应该真正地带来加法和减法的出独立以及使这一点更BODMAS符合。

大感谢Rajesh Jinaga他堆基础的方法。我找到它真的有用我的需要。以下代码是一个微小的修改Rajesh的方法,它处理的部门,然后乘法,然后完成了与加法和减法。它还将允许利用布尔在的表达形式,在那里真的是处理为1和虚假的0.允许使用的布尔逻辑的表达。

public static double Evaluate(string expr)
    {
        expr = expr.ToLower();
        expr = expr.Replace(" ", "");
        expr = expr.Replace("true", "1");
        expr = expr.Replace("false", "0");

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

        string value = "";
        for (int i = 0; i < expr.Length; i++)
        {
            String s = expr.Substring(i, 1);
            // pick up any doublelogical operators first.
            if (i < expr.Length - 1)
            {
                String op = expr.Substring(i, 2);
                if (op == "<=" || op == ">=" || op == "==")
                {
                    stack.Push(value);
                    value = "";
                    stack.Push(op);
                    i++;
                    continue;
                }
            }

            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;
                        bracketCount--;
                    }
                    innerExp += s;
                }
                stack.Push(Evaluate(innerExp).ToString());
            }
            else if (s.Equals("+") ||
                     s.Equals("-") ||
                     s.Equals("*") ||
                     s.Equals("/") ||
                     s.Equals("<") ||
                     s.Equals(">"))
            {
                stack.Push(s);
            }
            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;
        List<String> list = stack.ToList<String>();
        for (int i = list.Count - 2; i >= 0; i--)
        {
            if (list[i] == "/")
            {
                list[i] = (Convert.ToDouble(list[i - 1]) / Convert.ToDouble(list[i + 1])).ToString();
                list.RemoveAt(i + 1);
                list.RemoveAt(i - 1);
                i -= 2;
            }
        }

        for (int i = list.Count - 2; i >= 0; i--)
        {
            if (list[i] == "*")
            {
                list[i] = (Convert.ToDouble(list[i - 1]) * Convert.ToDouble(list[i + 1])).ToString();
                list.RemoveAt(i + 1);
                list.RemoveAt(i - 1);
                i -= 2;
            }
        }
        for (int i = list.Count - 2; i >= 0; i--)
        {
            if (list[i] == "+")
            {
                list[i] = (Convert.ToDouble(list[i - 1]) + Convert.ToDouble(list[i + 1])).ToString();
                list.RemoveAt(i + 1);
                list.RemoveAt(i - 1);
                i -= 2;
            }
        }
        for (int i = list.Count - 2; i >= 0; i--)
        {
            if (list[i] == "-")
            {
                list[i] = (Convert.ToDouble(list[i - 1]) - Convert.ToDouble(list[i + 1])).ToString();
                list.RemoveAt(i + 1);
                list.RemoveAt(i - 1);
                i -= 2;
            }
        }
        stack.Clear();
        for (int i = 0; i < list.Count; i++)
        {
            stack.Push(list[i]);
        }
        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) ? 1 : 0;
            else if (op == ">") result = (left > right) ? 1 : 0;
            else if (op == "<=") result = (left <= right) ? 1 : 0;
            else if (op == ">=") result = (left >= right) ? 1 : 0;
            else if (op == "==") result = (left == right) ? 1 : 0;

            stack.Push(result.ToString());
        }
        return Convert.ToDouble(stack.Pop());
    }

我知道有可能是一个更清洁的方式这样做,认为id只是分享的第一次看到它的情况下,任何人认为它有用的。

非常感谢Ramesh.我用一个版本,他的简单的代码拉串了一个数据库,并用它来做布林行动,在我的代码。

x是一个数字,例如1500或2100或什么的。

功能将是一个存储评价喜欢x>1400和x < 1600

function = relation[0].Replace("and","&&").Replace("x",x);

DataTable f_dt = new DataTable();
var f_var = f_dt.Compute(function,"");

if (bool.Parse(f_var.ToString()) { do stuff  }

没有。你将需要使用一些外部图书馆,或写入自己的分析程序。如果你有时间这样做,我建议编写自己的分析器,因为它是一个相当有趣的项目。否则你将需要使用什么样的 bcParser.

简短的回答:我不这么认为。C#。净额编制(字节码的)和不可能评估串在运行时,尽我所知道的。JScript。净可以,但是;但我仍建议你的代码分析和基于栈评估自己。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top