Jarloo

Menu

 

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) =>
Math.Cos(Convert.ToDouble(x.Groups[1].Value)).ToString());

if (expr.IndexOf(“sin”) != -1) expr = Do(sinRegex, expr, (x) =>
Math.Sin(Convert.ToDouble(x.Groups[1].Value)).ToString());

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:  , ,

Comments

Sorry, comments are closed for this item.