Tom’s Blog

December 2, 2008

A Simple Method for Evaluating Mathematical Expressions at Runtime

Filed under: General .NET — Tom Shelton @ 11:31 pm

Over the years, on the forums I frequent, the question has come up from time-to-time on how to dynamically evaluate expressions built at runtime.  Often, the suggestions range from dynamic code compilation to creating expression evaluators.  While these suggestions are not necessarily bad – they do have some drawbacks.

The main problem with dynamic code compilation, is that it is slow.  This may not be an issue if you are only going to do one or two calculations – but, if you need to perform your calculations hundreds or thousands of times, then the performance hit can become significant.  For example,  on the MSDN Visual C# forum, I was recently involved in a thread where the original poster was using dynamic compilation to evaluate expressions thousands of times and was looking for ways to speed up the process.  I suggested he try the method I am about to present here, and his processing time dropped from the approximately 7 hours to 49 seconds.  Not bad.

The other method, creating an expression evaluator, suffers from complexity.  It isn’t an easy task.  Of course, there are enough examples and pre-built libraries to perform this task that no one should have to write such a beast anymore (except maybe as an exercise).  But, why hunt down a third party library, when Microsoft has given us a built in expression evaluator?    Well, sort of. 

The expression evaluation mechanism that I am referring to is the JScript Eval method.  It seems that many do not realize that JScript is an official .NET language.  I suspect that is because the IDE has no built in support for JScript.NET.   Here is a method for creating a simple wrapper library to expose the JScript Eval method to your C# or VB program.

 

1.

Since there is no IDE support for the JScript.NET language, create and save the Evaluator.js file in the external text editor of your choice. 

 

image01

   

2.

Use the “Visual Studio 2008 Command Prompt” (Start -> Programs -> Microsoft Visual Studio 2008 -> Visual Studio Tools) to navigate to the directory that contains the Evaluator.js file.  Once there, compile the source, like this:

  image02
 

Ok, so I didn’t use the VS command prompt :)  I used the Windows PowerShell console.  I translated the bat file that the VS command prompt uses and put it in my $PROFILE.

   

3.

Now, create your Visual Basic or C# project.  Right click on your project in the Solution Explorer, and select “Add Reference…”.  On the .NET tab select Microsoft.JScript:

  image03
   

4.

Again, Right click on your project in the Solution Explorer, and select “Add Reference…”.   Select the “Browse” tab, and find and select the Evaluator.dll that we just compiled:

  image04
   

5.

Let’s write some code to use the dll.

C#
using System;
 
namespace CSharpExample
{
    class Program
    {
        static void Main ( string[] args )
        {
            string expression = string.Format ( "(Math.pow({0}, {1}) * {2}) / {3}", 50, 2, 3.5, 16.25 );
            Console.WriteLine ( Calculate ( expression ) );
        }
 
        static decimal Calculate ( string expression )
        {
            return Convert.ToDecimal ( new Evaluator ().Evaluate ( expression ) );
        }
    }
}
VB
Option Strict On
Option Explicit On
 
Module VBExample
 
    Sub Main()
        Dim expression As String = String.Format("(Math.pow({0}, {1}) * {2}) / {3}", 50, 2, 3.5, 16.25)
        Console.WriteLine(Calculate(expression))
    End Sub
 
    Function Calculate(ByVal expression As String) As Decimal
        Return Convert.ToDecimal(New Evaluator().Evaluate(expression))
    End Function
End Module

This example, is pretty simplistic – for example, the Calculate methods do not do any sort of checking to make sure that the expression passed is a valid mathematical expression.  I used the System.String.Format method to illustrate one way of getting values into an expression to be evaluated.  It should be noted that this method will not only evaluate mathematical expressions, but arbitrary JScript code.  As long as you are using a version of .NET >= 1.1, then this shouldn’t be much of an issue because unless you pass the string “unsafe” to the optional second parameter of the JScript Eval method, then the code will run in a limited security context.   If you decide to ever use the Eval method with the “unsafe” option, then you will want to make sure that all of your strings are obtained from a trusted source.

2 Comments »

  1. This worked perfectly on my development computer, but when I dropped it on the internet server it bombs!

    Help!

    Comment by Marc Brunelle — May 4, 2009 @ 2:38 pm

  2. Marc…

    It would be helpful to know how it bombs.

    Comment by Tom Shelton — May 5, 2009 @ 9:53 pm

RSS feed for comments on this post. TrackBack URL

Leave a comment

Powered by WordPress