Convert string to formula
-
Wednesday, March 07, 2012 4:03 AM
Hi All,
I developing layered architecture project in asp.net using C Sharp. I am storing the formula in database as string. After selecting the string I need to change it as formula. Whether its possible.
Example:
Input : formula given by user “(a+b)/c” store this as string because it change byuser at any time for example it can be “c/(a*b)”.
Now this formula will retrieve from database for calculation. Now another user will enter the values for parameter for “a”, “b” and “c” for above example.
Now in the code I need calculate the result. How?
Thanks
Prathap
All Replies
-
Wednesday, March 07, 2012 4:13 AM
I'm interested in this solution too. MSFT has long needed the ability to interpret strings as commands and or variables. The problem you will have is that there is no "Interpret" function in .NET framework that allows you to build a string that gets interpreted at run time. So the second best thing is that you will have to build a parser to parse and intrepret each piece of the equation. You are building a mini-compiler. Some people will point you to the CODEDOM class in .NET... The idea is that you are going to build a class of code and then run a compiler and run to code all at run time.
Others may point you to Generics where tricks are performed to get types back that you want.
There is another set of class you can use known as Expression Trees. It takes a while to learn but I'm confident you can build a lambda expression which is a function that returns a result all done via strings in the Expression tree.
JP Cowboy Coders Unite!
-
Wednesday, March 07, 2012 10:50 AM
You can use the DataColumn.Expression Property. It evaluates any expression like the javascript eval function.
So you can use it like this:
class Program { static void Main(string[] args) { string formula = "(a+b)/c"; // Take it from the data base or whatever... Console.WriteLine("Enter first number:"); string a = Console.ReadLine(); Console.WriteLine("Enter second number:"); string b = Console.ReadLine(); Console.WriteLine("Enter third number:"); string c = Console.ReadLine(); // Replace all letters with numbers formula = formula.Replace("a", a).Replace("b", b).Replace("c", c); // Evaluate the formula Console.WriteLine("Formula: {0}\tResult: {1}", formula, Evaluate(formula)); Console.ReadLine(); } public static double Evaluate(string expression) { DataTable table = new DataTable(); table.Columns.Add("myExpression", string.Empty.GetType(), expression); DataRow row = table.NewRow(); table.Rows.Add(row); return double.Parse((string)row["myExpression"]); } }Noam B.
Do not Forget to Vote as Answer/Helpful, please. It encourages us to help you...- Proposed As Answer by Noam B Wednesday, March 07, 2012 10:51 AM
- Marked As Answer by Prathap Kumar Wednesday, March 07, 2012 11:19 AM
-
Wednesday, March 07, 2012 11:10 AM
Noam, just one thing: what will happen if this is not the only formula? If there is like: "a*b / (c+d)" or what ever?
You have to create a dinamic code to seperated formula into pieces.
Mitja
-
Wednesday, March 07, 2012 11:18 AM
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);
Hope iot helps.Mitja
- Marked As Answer by Prathap Kumar Wednesday, March 07, 2012 11:41 AM
-
Wednesday, March 07, 2012 1:31 PM
Mitja;
Congratulations that's some pretty code there. Too bad it takes so much work to do this simple task. The op may be able to create expression trees as well, the only problem as your code points out is that there has to be massive support for parsing. As mentioned before, he is indeed having to write a mini-compiler/parser. But I think you're code is an excellent example of how to do this.
JP Cowboy Coders Unite!
-
Wednesday, March 07, 2012 3:04 PM
thx :)
I like coding, so ... hehe
Mitja
-
Saturday, October 13, 2012 7:51 PMBest and short answer i have seen as solution, let me dig deep into it, but if i directly say double.parse("string") is doesnt calculate the formula ? so there is something in the datatable
Y2KPRABU, MCTS,MCPD INDIA

