C# Formula Evaluator

Ever need to give your users the ability to enter in simple formulas into a TextBox and have it evaluated?  This is something I keep running across and after looking around a bit I couldn’t find a simple light-weight formula evaluator for C#, so I decided to build one.

What I wanted as a simple to use evaluator that accepts a string that looks similiar to this: “5 * 2 / 3”, and returns the correct answer.

The formula evaluator I created supports multiplication, division, addition, subtraction, powers, sin, cos and obeys brackets following the correct order of operations.

Formula Evaluator

using System;
using System.Text.RegularExpressions;

namespace JarlooFormulaEvaluator
public class FormulaEvaluator
private readonly Regex bracketsRegex = new Regex(@”([a-z]*)\(([^\(\)]+)\)(\^|!?)”, RegexOptions.Compiled);
private readonly Regex cosRegex = new Regex(@”cos(-?\d+.?\d*)”, RegexOptions.Compiled);
private readonly Regex sinRegex = new Regex(@”sin(-?\d+.?\d*)”, RegexOptions.Compiled);
private readonly Regex powerRegex = new Regex(@”(-?\d+\.?\d*)\^(-?\d+\.?\d*)”, RegexOptions.Compiled);
private readonly Regex multiplyRegex = new Regex(@”(-?\d+\.?\d*)\*(-?\d+\.?\d*)”, RegexOptions.Compiled);
private readonly Regex divideRegex = new Regex(@”(-?\d+\.?\d*)/(-?\d+\.?\d*)”, RegexOptions.Compiled);
private readonly Regex addRegex = new Regex(@”(-?\d+\.?\d*)\+(-?\d+\.?\d*)”, RegexOptions.Compiled);
private readonly Regex subtractRegex = new Regex(@”(-?\d+\.?\d*)-(-?\d+\.?\d*)”, RegexOptions.Compiled);

public double Evaluate(string expr)
expr = expr.Replace(” “, “”).ToLower();

Match m = bracketsRegex.Match(expr);
while (m.Success)
expr = expr.Replace(“(” + m.Groups[2].Value + “)”, Solve(m.Groups[2].Value));
m = bracketsRegex.Match(expr);

return Convert.ToDouble(Solve(expr));

private string Solve(string expr)
if (expr.IndexOf(“cos”) != -1) expr = Do(cosRegex, expr, (x) =>

if (expr.IndexOf(“sin”) != -1) expr = Do(sinRegex, expr, (x) =>

if (expr.IndexOf(“^”) != -1) expr = Do(powerRegex, expr, (x) =>
Math.Pow(Convert.ToDouble(x.Groups[1].Value), Convert.ToDouble(x.Groups[2].Value)).ToString());

if (expr.IndexOf(“/”) != -1) expr = Do(divideRegex, expr, (x) =>
(Convert.ToDouble(x.Groups[1].Value) / Convert.ToDouble(x.Groups[2].Value)).ToString());

if (expr.IndexOf(“*”) != -1) expr = Do(multiplyRegex, expr, (x) =>
(Convert.ToDouble(x.Groups[1].Value) * Convert.ToDouble(x.Groups[2].Value)).ToString());

if (expr.IndexOf(“+”) != -1) expr = Do(addRegex, expr, (x) =>
(Convert.ToDouble(x.Groups[1].Value) + Convert.ToDouble(x.Groups[2].Value)).ToString());

if (expr.IndexOf(“-“) != -1) expr = Do(subtractRegex, expr, (x) =>
(Convert.ToDouble(x.Groups[1].Value) – Convert.ToDouble(x.Groups[2].Value)).ToString());

return expr;

private static string Do(Regex regex, string formula, Func func)
MatchCollection collection = regex.Matches(formula);

if (collection.Count == 0) return formula;

for (int i = 0; i < collection.Count;i++ ) formula = formula.Replace(collection[i].Groups[0].Value, func(collection[i])); formula = Do(regex, formula, func); return formula; } } } [/csharp] And to use the code you need could do something like this: [csharp] namespace JarlooFormulaEvaluator { internal class Program { private static void Main(string[] args) { FormulaEvaluator eval = new FormulaEvaluator(); //Simple math Console.WriteLine(string.Format("5*2={0}", eval.Evaluate("5*2"))); //Default order of operations Console.WriteLine(string.Format("5*2+3={0}", eval.Evaluate("5*2+3"))); //Brackets are solved first Console.WriteLine(string.Format("5*(2+3)={0}", eval.Evaluate("5*(2+3)"))); //Can use sin / cos Console.WriteLine(string.Format("5*(2+sin(3))={0}", eval.Evaluate("5*(2+sin(3))"))); //Can raise to the power of Console.WriteLine(string.Format("5*(2+sin(3))/2^2={0}", eval.Evaluate("5*(2+sin(3))/2^2"))); Console.ReadLine(); } } [/csharp] You can easily add new functions by including a new Regex and making a new entry in the Solve method. [box type="shadow"]Works under Microsoft .NET Framework version 4.[/box]

Categories:   Code

Tags:  , ,


  • Posted: January 21, 2011 13:19


    I'm new to C# and wanted to understand the logic behind your parser. However i can't seem to understand the source code. I tried to compile the code to sebug and step through however i ge many errors, particularly in the Solve and Do methods. It seems that there are random =&gt and &lt etc in the code that dont compile. I also cant make out what the parameters are for the Do method. Would you mind posting again so i can get to grips with this project. By the way i have found your site very useful and the design is excellent. Regards
    • Posted: January 21, 2011 13:41


      Sorry about that. I changed the module used to display code on the site and obviously missed updating this article. It's now fixed.
  • Posted: January 25, 2011 13:29


    Thanks! I think i understand delegates and lambda expressions a lot more now. Just out of interest how would you implement the evaluation of Pi or other constants in this example? Would it be best to replace them with the actual value before evaluation or create another Regex to deal with them?
    • Posted: January 25, 2011 13:50


      I would create another regex just like the COS and SIN ones to handle PI or constants.
      • Posted: January 25, 2011 15:04


        Wouldn't they have to be slightly different though as you don't have to have two operands when using constants. Would it end up replacing the words with the constant via a Regex rather than using the .Replace method?
      • Posted: January 25, 2011 17:35


        Your right. Replacing would be easier. For example in the Evaluate method you could do this for PI: expr = expr.Replace("pi", Math.PI.ToString()).ToLower(); You could do the same for other constants, or better yet write a method that lets you assign constants to the engine. Could be as simple as a public method like: public Dictionary Constants {get; set;} Then iterate it at the beginning of the Evaluate method and do the replacements.
  • Posted: January 26, 2011 13:15


    Great suggestion! Ona slightly different note is there a way to slightly modify the Regex's so that they accept the operand in brackets as well as without? e.g sin(45) rather than just sin45. Thanks
  • Posted: January 26, 2011 13:31


    It already does. Since it does order of operations it will solve for the brackets first then essentially replace the brackets and their contents with the value. Then it will solve from there. So if you enter sin(45), it will replace (45) with 45, so you have sin45, then it will solve that and it will match the regex and process properly. You could also do sin(45-10) and it will work properly since it does the brackets first.
  • Posted: January 26, 2011 13:47


    I was just thinking of a method to put brackets around the whole expression e.g (sin(45) instead of sin(45) as there is a bug if you do for example sin(45) + cos(45), fixed by putting brackets around each individual expression
  • Posted: January 31, 2011 10:03


    Managed to fix the bug by looping through all of the regex's in a set and inserting brackets encapsulating each expression found in a MatchCollection. Also had to do this twice - once at the beginning of the Evaluate method and once after the brackets had been matched. Also had to match brackets again after brackets had been put in. Not the best fix in terms of efficiency, but it works well.
  • Posted: February 10, 2011 00:28


    Write unit test for FormulaEvaluator. Wrong calculation for decimals value. Example, 5,1-2,9 To fix bug change ".?" to ".?" in all regexp!
    • Posted: February 11, 2011 11:48


      Is this a localization issue? Are the "," in your example used to denote the difference between dollars and cents? ie: a decimal place like "." for U.S.
  • Posted: February 11, 2011 11:39


    What do you mean by wrong calculation for decimals value? All tests that iv done turn out perfecty. What do you mean by 5,1-2,9?
  • Posted: February 11, 2011 11:47


    Oh sorry, i see what you mean now. Its because this evaluator does not support comma's as a method of signifying decimal points, only periods. As you said if you want to change it to accept comma's, you can modify the regex expressions
  • Posted: February 23, 2011 13:08


    Hi again, Sorry to bother you again but i was wondering if you might give me some pointers. Its kind of related to this topic in terms of Regex's. I am in the middle of a project involving some functions on equations such as gradient(x^2 + 7x +12). I was thinking that i could modify some of the Regex expressions above to return the value 7 in this case. However i came to a halt in the large matter of the brackets. At the moment, like above, the brackets are done first (which is fine) however when it comes to doing the calculation on the equation, the program doesnt know where the equation ends and would simply go on and on to the rest of the expression - resulting in the complete wrong result. I was wondering if you knew a possible solution to this, where brackets are still taken into consideration, yet the gradient function for example can still work properly. Thanks again
  • Posted: June 25, 2011 21:49


    Formula below won't work for example...I believe somehow the exponent E is messing it up. (-4.1855)^2+(0.0000005)^3+(-2.1521)^2
  • Posted: January 9, 2012 18:07

    Clifford Nelson

    Your regular expression definitions are missing the back slashes before the 'd' and special characters. Fixed that but still having problems.
  • Posted: January 11, 2012 15:53


    As you mentioned the regex were missing some of the backslashes. (format issue when I posted it. sorry about that.) I've corrected the issue. Should work for you now.
  • Posted: May 10, 2012 10:28


    Merci cent millions de fois! Très puissant!
  • Posted: May 11, 2012 09:49


    my english is not very good: ( receive health care. very nice sharing. I'm new in c #. I got an error like this program. Convert.ToDouble return (Solve (expr)); / Input string was not in a correct format. If you help rejoice. Thank you.
  • Posted: May 16, 2012 11:46

    Fred Knot

    HASAN , check the formula you are passing in. Could it be incorrect? Try something simple like: eval.Evaluate("5*2") I got the same error that you got when I had an incorrect forumla. I had more "("'s than ")"'s so it couldn't evaluate properly- when I fixed my formula it worked. Good luck.
  • Posted: January 4, 2013 02:37


    that's nice, thank u so much :) Good luck
  • Posted: February 25, 2013 12:54


    Hi, i am using your formula evaluator.it is not working in some cases .could you please help me. for example 0+0+0.00+0.00+0.00 this format not working
  • Posted: February 17, 2014 09:39


    I´ve found a problem something like 1+1+5+1+1000 on the replace returned 2+5+2000 then, i´ve changed the code: for (int i = 0; i < collection.Count;i++ ) formula = formula.Replace(collection[i].Groups[0].Value, func(collection[i])); for the code: for (int i = 0; i < collection.Count; i++) { //formula = formula.Replace(collection[i].Groups[0].Value, func(collection[i])); string first_operation = collection[i].Groups[0].Value; int len = first_operation.Length; int pos = formula.IndexOf(first_operation); string formula_before_operation = formula.Substring(0, pos); string formula_after_operation = formula.Substring(pos+len, formula.Length - (pos+len)); formula = formula_before_operation + func(collection[i]) + formula_after_operation; }
  • Posted: June 2, 2014 07:46


    I have some problems. If i try 1-2^2, it returns 14 because it calculates (-2^2) = 4 and concatenates to the "1" remaining. Can't find a way to resolve it ...