Click here to Skip to main content
11,637,415 members (57,426 online)
Click here to Skip to main content

Parsing Mathematical Expressions with muParser

, 3 Mar 2012 MIT 159.4K 3.8K 144
Rate this:
Please Sign up or sign in to vote.
A wrapper for the muParser DLL
muParser_cs.jpg

Introduction

This article features a C# wrapper for the muParser DLL. muParser is a fast mathematical expressions parser which transforms a mathematical expression into bytecode. Since writing it, I have received some queries about using the parser with .NET. So far, no real solution existed since muParser is native C++ code. This project will close the gap between the unmanaged parser DLL and the managed .NET environment. It is not meant to give you a detailed overview on muParser itself. Please use the following pages for this:

The functionality and member functions of the C# wrapper are almost identical, with a few exceptions mentioned in this document.

Features

The aim of this code is to provide a complete wrapper of muParser. Some of the more advanced and rarely used features could not be made accessible due to their intrinsic "unmanaged" nature. The following list shows you what features are available in C#:

  • User-defined operators
    • binary operators
    • postfix operators
    • infix operators
  • User-defined functions
    • with a fixed number of up to five arguments
    • with variable number of arguments
    • with a single string argument (for database queries)
  • User-defined constants
    • numeric constants
    • string constants
  • User-defined variables
    • unlimited in number
    • assigning variables in terms of other variables is possible
  • Custom value recognition callbacks
    • support for binary and hex values
    • can be used to implement database queries
  • Parser functions/operators

Built-in Functions

The following table gives an overview of the functions supported by the default implementation. It lists the function names, the number of arguments and a brief description.

Name Argc. Explanation
sin 1 sine function
cos 1 cosine function
tan 1 tangens function
asin 1 arcus sine function
acos 1 arcus cosine function
atan 1 arcus tangens function
sinh 1 hyperbolic sine function
cosh 1 hyperbolic cosine
tanh 1 hyperbolic tangens function
asinh 1 hyperbolic arcus sine function
acosh 1 hyperbolic arcus tangens function
atanh 1 hyperbolic arcus tangens function
log2 1 logarithm to the base 2
log10 1 logarithm to the base 10
log 1 logarithm to the base 10
ln 1 logarithm to base e (2.71828...)
exp 1 e raised to the power of x
sqrt 1 square root of a value
sign 1 sign function, -1 if x<0; 1 if x>0
rint 1 round to nearest integer
abs 1 absolute value
if 3 if ... then ... else ...
min var. min of all arguments
max var. max of all arguments
sum var. sum of all arguments
avg var. mean value of all arguments

Built-in Binary Operators

The following table lists the default binary operators supported by the parser:

Operator Meaning Priority
= assignment* -1
and logical AND 1
or logical OR 1
xor logical XOR 1
<= less or equal 2
>= greater or equal 2
!= not equal 2
== equal 2
> greater than 2
< less than 2
+ addition 3
- subtraction 3
* multiplication 4
/ division 4
^ raise x to the power of y 5

*The assignment operator is special since it changes one of its arguments and can only be applied to variables.

How It Works

The wrapper defines three classes:

  • muParser.Parser

    This is the parser object. You need to create an instance of this object in order to calculate an expression. Look at the muParser homepage for more detailed description.

  • muParser.ParserException
  • muParser.ParserVariable

Parser and ParserException are similar to their C++ counterparts and will not be documented here in detail. For details, refer to the C++ documentation and the sample source code.

ParserVariable is new and encapsulates a double value used as a variable. This is necessary since for each variable muParser needs a pointer to double. Using C#, it is hard to get a pointer that remains fixed during the lifetime of a class. ParserVariable avoids this trouble by using the DLL itself to create and release a pointer to double. In short, it hides the variable pointer from the garbage collector.

Using the Code

In order to use the code, you need the muParser.dll which is part of this archive. Make sure to place a copy of the DLL into your application directory or in a directory where the system can find it. Finally, add the file muParser.cs to your project. The following code samples assume you are either in namespace muParser or have a corresponding using muParser  statement.  

Setting Up the Parser 

In order to use the parser, create an instance of it.

 Parser parser = new Parser(Parser.EBaseType.tpDOUBLE); 
By using Parser.EBaseType.tpINT or Parser.EBaseType.tpDOUBLE as a parameter to the parser constructor you can either select an instance working with integer values or the standard instance working with double values.

Defining Variables  

Create an instance of a ParserVariable and set up a corresponding parser variable. You can default initialize the variable to a user defined value using the constructor.

ParserVariable var = new ParserVariable(10);
parser.DefineVar("my_var", var);

Setting Up and Calculating an Expression

Finally, set up the expression and calculate the result.

parser.SetExpr("10*sin(my_var)");
double val = parser.Eval();

Defining Custom Functions

You can set up your own functions and operators using delegates. The parser defines the following type that must be implemented in your code in case you'd like to use custom functions:

// Functions taking double arguments
public delegate double Fun1Delegate(double val1);
public delegate double Fun2Delegate(double val1, double val2);
public delegate double Fun3Delegate(double val1, double val2, double val3);
public delegate double Fun4Delegate(double val1, double val2, double val3, 
    double val4);
public delegate double Fun5Delegate(double val1, double val2, double val3, 
    double val4, double val5);

// Functions taking an additional string parameter
public delegate double StrFun1Delegate(String name);
public delegate double StrFun2Delegate(String name, double val1);
public delegate double StrFun3Delegate(String name, double val1, double val2);

  // Functions taking unlimited number of variables
  public delegate double MultFunDelegate(
      [MarshalAs(UnmanagedType.LPArray, SizeParamIndex=1)] double[] array,
      int size);

Registering callbacks can be done like this:

// Add additional parser functions [optional]
parser.DefineFun("fun1", new muParser.Fun1Delegate(fun1) );
parser.DefineFun("fun2", new muParser.Fun2Delegate(fun2) );
parser.DefineFun("fun3", new muParser.Fun3Delegate(fun3) );
parser.DefineFun("fun4", new muParser.Fun4Delegate(fun4) );
parser.DefineFun("fun5", new muParser.Fun5Delegate(fun5) );
parser.DefineFun("prod", new muParser.MultFunDelegate(prod) );

// add additional operators [optional]
parser.DefineOprt("%", new muParser.Fun2Delegate(fun2), 2 );
parser.DefinePostfixOprt("m", new muParser.Fun1Delegate(fun1));

The first parameter to DefineFun or DefineOprt is the identifier, the second parameter is the delegate used as callback.

Dealing with Errors

Errors are reported by throwing an exception of type ParserException. Use the member functions of this class to get the error details.

try
{
    parser = new muParser();

    // use parser
    //...
    //...
    //...
}
catch (ParserException exc)
{
    string sMsg;
    sMsg += string.Format("  Expression:  \"{0}\"\n", exc.Expression);
    sMsg += string.Format("  Message:     \"{0}\"\n", exc.Message);
    sMsg += string.Format("  Token:       \"{0}\"\n", exc.Token);
    sMsg += string.Format("  Position:      {0}\n", exc.Position);

    Console.WriteLine(sMsg);
}

License

Copyright (c) 2007 Ingo Berg

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

History

  • Rev. 1.00 - 09.04.2007
    Initial release of the muParser C# wrapper

License

This article, along with any associated source code and files, is licensed under The MIT License

Share

About the Author

iberg
Software Developer
Germany Germany
No Biography provided

You may also be interested in...

Comments and Discussions

 
QuestionProblem while deploying on IIS Pin
Bhavin Jagad13-Aug-13 6:54
memberBhavin Jagad13-Aug-13 6:54 
GeneralMy vote of 5 Pin
Abinash Bishoyi11-Jan-13 3:04
memberAbinash Bishoyi11-Jan-13 3:04 
Question64 bit update Pin
Member 943881215-Nov-12 10:28
memberMember 943881215-Nov-12 10:28 
QuestionExplicitely defining variables Pin
Black Climber30-Oct-12 10:09
memberBlack Climber30-Oct-12 10:09 
AnswerRe: Explicitely defining variables Pin
Daedeross25-Oct-13 15:37
memberDaedeross25-Oct-13 15:37 
QuestionUsing wrapper with Mono proyect in Linu Pin
Juan Jose Perez12-Oct-12 22:40
memberJuan Jose Perez12-Oct-12 22:40 
QuestionPretty sweet visual. Pin
badymojoy13-Aug-12 23:15
memberbadymojoy13-Aug-12 23:15 
AnswerRe: Pretty sweet visual. Pin
iberg14-Aug-12 8:38
memberiberg14-Aug-12 8:38 
Questionhow can I add muparser dll to my visualstudio2010? Pin
sivadasu7-Jun-12 18:50
membersivadasu7-Jun-12 18:50 
Question5 out of 5! Pin
Aamer Alduais11-May-12 3:15
memberAamer Alduais11-May-12 3:15 
GeneralMy vote of 5 Pin
RusselSSC4-Mar-12 3:08
memberRusselSSC4-Mar-12 3:08 
QuestionCould you tell me how to fix these errors? Pin
Member 86841122-Mar-12 23:02
memberMember 86841122-Mar-12 23:02 
QuestionCould you tell me where I can get the muParser.dll? Pin
Member 868411229-Feb-12 23:34
memberMember 868411229-Feb-12 23:34 
AnswerRe: Could you tell me where I can get the muParser.dll? Pin
iberg1-Mar-12 1:25
memberiberg1-Mar-12 1:25 
GeneralRe: Could you tell me where I can get the muParser.dll? Pin
Member 86841122-Mar-12 22:42
memberMember 86841122-Mar-12 22:42 
GeneralRe: Could you tell me where I can get the muParser.dll? Pin
sivadasu7-Jun-12 18:46
membersivadasu7-Jun-12 18:46 
GeneralMy vote of 5 Pin
Prafulla Hunde31-Jan-12 8:16
memberPrafulla Hunde31-Jan-12 8:16 
GeneralMy vote of 4 Pin
Humayun Kabir Mamun3-Nov-11 0:13
memberHumayun Kabir Mamun3-Nov-11 0:13 
Question.NET and 2.0 Pin
iscoh2-Nov-11 0:07
memberiscoh2-Nov-11 0:07 
AnswerRe: .NET and 2.0 Pin
iberg2-Nov-11 10:07
memberiberg2-Nov-11 10:07 
Generalgreat work! Pin
Member 401148828-Mar-11 16:41
memberMember 401148828-Mar-11 16:41 
GeneralC# wrapper for the muParser DLL Sample solution in Visual Studio Express 2010 [modified] Pin
pleabo4-Nov-10 7:55
memberpleabo4-Nov-10 7:55 
GeneralRe: C# wrapper for the muParser DLL Sample solution in Visual Studio Express 2010 [modified; issue fixed] Pin
iberg6-Nov-10 7:14
memberiberg6-Nov-10 7:14 
GeneralRe: C# wrapper for the muParser DLL Sample solution in Visual Studio Express 2010 [modified; issue fixed] [modified] Pin
pleabo10-Nov-10 0:28
memberpleabo10-Nov-10 0:28 
Generalmuparser in Visual Studios 2010 Pin
Member 743864716-Sep-10 10:12
memberMember 743864716-Sep-10 10:12 
QuestionHow to use the remiander function of tow value, as 5%3 = 2 Pin
mini_stone17-Aug-10 15:36
groupmini_stone17-Aug-10 15:36 
AnswerRe: How to use the remiander function of tow value, as 5%3 = 2 Pin
iberg17-Aug-10 20:53
memberiberg17-Aug-10 20:53 
GeneralThanks! Good work Pin
farshidmaj27-May-10 8:38
memberfarshidmaj27-May-10 8:38 
NewsArchive Updated Pin
iberg12-Jan-10 13:25
memberiberg12-Jan-10 13:25 
GeneralRe: Archive Updated Pin
chapelet2-Feb-10 3:47
memberchapelet2-Feb-10 3:47 
GeneralRe: Archive Updated [modified] Pin
iberg2-Feb-10 11:19
memberiberg2-Feb-10 11:19 
GeneralRe: Archive Updated Pin
chapelet3-Feb-10 2:32
memberchapelet3-Feb-10 2:32 
GeneralRe: Archive Updated Pin
iberg3-Feb-10 3:41
memberiberg3-Feb-10 3:41 
QuestionBadImageFormatException Pin
Cedrik Meier6-Dec-09 8:27
memberCedrik Meier6-Dec-09 8:27 
AnswerRe: BadImageFormatException Pin
JamesXI17-Dec-09 8:48
memberJamesXI17-Dec-09 8:48 
GeneralRe: BadImageFormatException Pin
iberg17-Dec-09 10:23
memberiberg17-Dec-09 10:23 
QuestionHow to extend the muparser to have User defined functions having multiple string parameters Pin
Ananda Sreenivas12-Oct-09 22:56
memberAnanda Sreenivas12-Oct-09 22:56 
AnswerRe: How to extend the muparser to have User defined functions having multiple string parameters Pin
iberg13-Oct-09 11:25
memberiberg13-Oct-09 11:25 
GeneralNice Pin
Erik Molenaar18-Jun-09 7:38
memberErik Molenaar18-Jun-09 7:38 
GeneralQuestion about nulls Pin
Ram Cronus11-Mar-09 4:32
memberRam Cronus11-Mar-09 4:32 
GeneralRe: Question about nulls Pin
iberg11-Mar-09 7:10
memberiberg11-Mar-09 7:10 
GeneralRe: Question about nulls Pin
Ram Cronus11-Mar-09 11:52
memberRam Cronus11-Mar-09 11:52 
GeneralRe: Question about nulls Pin
iberg11-Mar-09 22:55
memberiberg11-Mar-09 22:55 
GeneralRe: Question about nulls Pin
Ram Cronus11-Mar-09 23:32
memberRam Cronus11-Mar-09 23:32 
GeneralUsing this parser for smart device applications Pin
Member 22777668-Mar-09 13:00
memberMember 22777668-Mar-09 13:00 
GeneralRe: Using this parser for smart device applications Pin
iberg26-Mar-09 1:17
memberiberg26-Mar-09 1:17 
GeneralArchive updated to muParser V1.31 Pin
iberg19-Jan-09 8:56
memberiberg19-Jan-09 8:56 
QuestionHow about memory leaks in the unmanaged code? Pin
Adrian Olszewski3-Jan-09 5:44
memberAdrian Olszewski3-Jan-09 5:44 
AnswerRe: How about memory leaks in the unmanaged code? Pin
iberg3-Jan-09 13:02
memberiberg3-Jan-09 13:02 
GeneralAccessViolatingException [modified] Pin
Otis66631-Oct-08 3:07
memberOtis66631-Oct-08 3:07 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Terms of Use | Mobile
Web01 | 2.8.150728.1 | Last Updated 3 Mar 2012
Article Copyright 2007 by iberg
Everything else Copyright © CodeProject, 1999-2015
Layout: fixed | fluid