how to convert a string to a mathematical expression programmatically

后端 未结 5 1978
时光说笑
时光说笑 2020-12-20 23:32

I am a beginner at C#. I am facing a problem while converting a string to a mathematical expression. I have a UI where user can create formula using random formula field. An

相关标签:
5条回答
  • 2020-12-21 00:00
    string input= "(12 + 4 * 6) * ((2 + 3 * ( 4 + 2 ) ) ( 5 + 12 ))";       
        string str4 = "(" + input`enter code here`.Replace(" ", "") + ")";
                str4 = str4.Replace(")(", ")*(");
                while (str4.Contains('('))
                {
                    string sub1 = str4.Substring(str4.LastIndexOf("(") + 1);
                    string sub = sub1.Substring(0, sub1.IndexOf(")"));
                    string sub2 = sub;
                    string str21 = sub2.Replace("^", "~^~").Replace("/", "~/~").Replace("*", "~*~").Replace("+", "~+~").Replace("-", "~-~");
                    List<string> str31 = str21.Split('~').ToList();
                    while (str31.Count > 1)
                    {
                        while (str31.Contains("*"))
                        {
                            for (int i = 0; i < str31.Count; i++)
                            {
                                if (str31[i] == "*")
                                {
                                    val = Convert.ToDouble(str31[i - 1]) * Convert.ToDouble(str31[i + 1]);
                                    str31.RemoveRange(i - 1, 3);
                                    str31.Insert(i - 1, val.ToString());
                                }
                            }
                        }
                        while (str31.Contains("/"))
                        {
                            for (int i = 0; i < str31.Count; i++)
                            {
                                if (str31[i] == "/")
                                {
                                    val = Convert.ToDouble(str31[i - 1]) / Convert.ToDouble(str31[i + 1]);
                                    str31.RemoveRange(i - 1, 3);
                                    str31.Insert(i - 1, val.ToString());
                                }
                            }
                        }
                        while (str31.Contains("+"))
                        {
                            for (int i = 0; i < str31.Count; i++)
                            {
                                if (str31[i] == "+")
                                {
                                    val = Convert.ToDouble(str31[i - 1]) + Convert.ToDouble(str31[i + 1]);
                                    str31.RemoveRange(i - 1, 3);
                                    str31.Insert(i - 1, val.ToString());
                                }
                            }
                        }
                        while (str31.Contains("-"))
                        {
                            for (int i = 0; i < str31.Count; i++)
                            {
                                if (str31[i] == "-")
                                {
                                    val = Convert.ToDouble(str31[i - 1]) - Convert.ToDouble(str31[i + 1]);
                                    str31.RemoveRange(i - 1, 3);
                                    str31.Insert(i - 1, val.ToString());
                                }
                            }
                        }
                    }
                    str4 = str4.Replace("(" + sub + ")", str31[0].ToString());
                }
    
                string sum = str4;
    
    0 讨论(0)
  • 2020-12-21 00:14

    i think this is the solution

     Expression e = new Expression("((a+b+c)^n+b)");
     e.Evaluate();
    
    0 讨论(0)
  • 2020-12-21 00:14

    The most structural approach which comes to my mind would be to define a grammar consisting out of operator symbols (which are apparently +,-,*,/ and ^ in your case) and operands; then, if a derivation of the input in the defined grammar exists, the derivation basically is the expression tree which can then be traversed recursively while the operators are directry translated to the actual operations. I admit that the description is a bit vague, but good parsing can be a bit difficult. Perhaps a look at LL parser can help a bit.

    0 讨论(0)
  • 2020-12-21 00:16

    There are plenty methods for formula evaluation, take a look. Just take your input, replace a, b, n chars in your string to values provided by user and resolve equation with one of methods mentioned.

    0 讨论(0)
  • 2020-12-21 00:21

    This is how it should be done:

    public class StringToFormula
    {
        private string[] _operators = { "-", "+", "/", "*","^"};
        private  Func<double, double, double>[] _operations = {
            (a1, a2) => a1 - a2,
            (a1, a2) => a1 + a2,
            (a1, a2) => a1 / a2,
            (a1, a2) => a1 * a2,
            (a1, a2) => Math.Pow(a1, a2)
        };
    
        public double Eval(string expression)
        {
            List<string> tokens = getTokens(expression);
            Stack<double> operandStack = new Stack<double>();
            Stack<string> operatorStack = new Stack<string>();
            int tokenIndex = 0;
    
            while (tokenIndex < tokens.Count) {
                string token = tokens[tokenIndex];
                if (token == "(") {
                    string subExpr = getSubExpression(tokens, ref tokenIndex);
                    operandStack.Push(Eval(subExpr));
                    continue;
                }
                if (token == ")") {
                    throw new ArgumentException("Mis-matched parentheses in expression");
                }
                //If this is an operator  
                if (Array.IndexOf(_operators, token) >= 0) {
                    while (operatorStack.Count > 0 && Array.IndexOf(_operators, token) < Array.IndexOf(_operators, operatorStack.Peek())) {
                        string op = operatorStack.Pop();
                        double arg2 = operandStack.Pop();
                        double arg1 = operandStack.Pop();
                        operandStack.Push(_operations[Array.IndexOf(_operators, op)](arg1, arg2));
                    }
                    operatorStack.Push(token);
                } else {
                    operandStack.Push(double.Parse(token));
                }
                tokenIndex += 1;
            }
    
            while (operatorStack.Count > 0) {
                string op = operatorStack.Pop();
                double arg2 = operandStack.Pop();
                double arg1 = operandStack.Pop();
                operandStack.Push(_operations[Array.IndexOf(_operators, op)](arg1, arg2));
            }
            return operandStack.Pop();
        }
    
        private string getSubExpression(List<string> tokens, ref int index)
        {
            StringBuilder subExpr = new StringBuilder();
            int parenlevels = 1;
            index += 1;
            while (index < tokens.Count && parenlevels > 0) {
                string token = tokens[index];
                if (tokens[index] == "(") {
                    parenlevels += 1;
                }
    
                if (tokens[index] == ")") {
                    parenlevels -= 1;
                }
    
                if (parenlevels > 0) {
                    subExpr.Append(token);
                }
    
                index += 1;
            }
    
            if ((parenlevels > 0)) {
                throw new ArgumentException("Mis-matched parentheses in expression");
            }
            return subExpr.ToString();
        }
    
        private List<string> getTokens(string expression)
        {
            string operators = "()^*/+-";
            List<string> tokens = new List<string>();
            StringBuilder sb = new StringBuilder();
    
            foreach (char c in expression.Replace(" ", string.Empty)) {
                if (operators.IndexOf(c) >= 0) {
                    if ((sb.Length > 0)) {
                        tokens.Add(sb.ToString());
                        sb.Length = 0;
                    }
                    tokens.Add(c);
                } else {
                    sb.Append(c);
                }
            }
    
            if ((sb.Length > 0)) {
                tokens.Add(sb.ToString());
            }
            return tokens;
        }
    }
    

    Call the class and method like this:

    string formula = "type your formula here"; //or get it from DB
    StringToFormula stf = new StringToFormula();
    double result = stf.Eval(formula);
    
    0 讨论(0)
提交回复
热议问题