Math Parser for C++

C++ Math Parser Rocks!

C++ developers can enjoy productivity gains with a Math Parser template class that allows pluggable types!

bcParserCPP Mathematical Expression Parser for C++ parses and evaluates math expressions given as strings at runtime. Parsing formulas given as strings at runtime is a challenge for any programmer when he wants to allow the user input a mathematical formula. bcParserCPP makes it easy for you! C++ language, with it’s expressive syntax, capable libraries and data structures makes it possible to implement a re-usable solution for the expression parsing problem. bcParserCPP – Math Parser for C++ – simplifies the task for us by implementing the parsing and evaluation algorithm. The expression is first parsed into an expression tree. Once this is done, the compiled tree structure is re-used with different variable values to achieve very fast evaluation performance.

bcParserCPP Math parser is implemented in C++. It is very flexible due to it’s C++ template based design and Object Oriented architecture. It allowes the programmer set the expression as a string, create user defined variables, set their values, create user defined functions and get expression value with one function call. The expression can contain arithmetic operators, logical operators, variables, functions, and numeric literals.
A simple example looks like this:

MathParser.SetExpression("x+sin(x)");
MathParser.SetX(3);
MathParser.SetY(2);
double value = MathParser.getValue();

The programmer can implement his own functions in C or C++ language and hook them up to the Math Parser object so that they can be used in expressions all with few lines of code.

The Math Parser reports errors via ParserException. This exception object carries out syntax errors that indicate invalid portion of the mathematical expression. The Math Parser class is template based and the numeric type that it uses can be plugged in. Typical use is with float, double, long double types. But it is possible to hookup user defined numeric types that implement necessary operators to support arbitrary precision arithmetic. bcParserCPP has been tested with std::complex for complex types and MAPM type for arbitrary precision arithmetic.

The variable and function names, and error messages are communicated using a string class. By default, this is the basic_string of standard C++ library. string for ascii and wstring for unicode are both supported.

Tackling all of the challenges of implementing a parser is almost impossible within the scope of a broader project where there are pressing requirements in terms of time and functionality to be delivered. Most of us need to focus on the actual business problem at hand and view the mathematical expression parsing aspect of the problem as a side issue. Thus, it becomes very very hard to deliver correct, united tested, proven code on time and in budget. bcParserCPP can help you save valuable time and help you focus on other important needs of your project by handling the tedious and detail oriented parsing needs.

bcParserPP C++ math parser is a well tested, simple C++ Class that can save time and money for experienced or novice programmers alike. It comes as a C++ Header file soure code so you are never stuck with a black box. Template based, C++ Object Oriented implementation makes it possible to customize many aspects of the parser. There is no library to link, just include the C++ header file and you are all set. It’s a breeze to use and pleasure to see in action. It supports Visual C++, Borland C++ and GNU C++ on Windows, Linux, Mac OS X.

Example of a User Defined Variable in bcParserCPP

You can define your own variables in bcParserCPP. Simplest way is to set a value for a variable and that will define it:

  //Define a MathParser type using types we like:
  //String will be based on TCHAR, numeric values will be double.
  typedef CMathParser<TCHAR, double> MathParser;
...
  MathParser p; //Define an instance of MathParser
  p.SetVariable("E", 2); //Define variable E with the value of 2
  p.SetVariable("P", 3); //Define variable P with the value of 3
  p.SetExpression("0*E-1*P"); //Not getting confused with E scientific notation
  cout << p.GetExpression() << endl; 
  cout << p.GetValue() << endl;
  cout << "Is variable P used? " << p.IsVariableUsed("P") << endl;

Callback function to return variable values

Sometimes it is not possible to predefine variables in a dynamic environment. We simply don’t know what variables the user may choose to use. In that case, it is possible to define a callback function that will return the value of a variable that is not previously defined:

/**
 * Variable callback example that is invoked whenever the math parser needs the value
 * of an unregistered variable. 
 * MathParser::string_t is the std::basic_string that is using the char type passed to 
 * the CMathParser template.
 */
double variableCallback(MathParser* pParentParser, MathParser::string_t VarName){
  if(VarName=="A"){
    return 5.0; //the value for variable A shall be 5.
  }
  throw MathParser::ParserException(MathParser::string_t("Unknown variable ")+VarName);
}

Here is how we can use this variable callback function:

    
MathParser p;
p.SetVariable("X", 2);
p.SetVariable("Y", 1);
//Register a callback to return variable value for given variable name.
p.SetVariableCallback(variableCallback);
p.SetExpression("X/Y+A-IF(A>1, 1, 0)"); // A is not predefined.
cout << p.GetExpression() << endl; 
cout << p.GetValue() << endl;
//You can check if a variable is used in the expression:
if(p.IsVariableUsed("A")){
  cout << "Yes, A is used." << endl;
}else{
  throw MathParser::ParserException("A is not used.");
}
if(!p.IsVariableUsed("B")){
  cout << "No, B is not used." << endl;
}else{
  throw MathParser::ParserException("B is not used.");
}

Example of a User Defined Function in Math Parser for C++

You can define your own functions to be called by the bcParserCPP during expression evaluation. The name of the function used in the math formula is independent of the actual function name in the C++ program. A user defined function implementation can look like this in C++: (assuming double numeric type is being used for CMathParser template)

/**
 * User defined function example that multiplies all parameters with each other and 
 * returns the result.
 * Can be used with a math parser that works with 'double' values.
 * (Hint: Use C++ templates to create functions that work with parametrized types) 
 */
double mult(MathParser* pParentParser, const double p[], const int count){
    double result = 1;
    for(int i=0; i < count; i++){
      result*=p[i];
    }
    return result;
}

This function can be registered with the parser instance so that it can be called within an expression.
Here is a simple example:

  MathParser p;
  //Register a user defined function:
  //First parameter is function name that will appear in expressions.
  //Second parameter is number of parameters the function takes.
  //-1 means any number of parameters is allowed.
  //When the number of parameters to a function is known, it is better
  //to specify it so that the expression parser can detect invalid number
  //of parameters, instead of leaving parameter count validation to the 
  //function itself.
  //Last parameter is the function address.
  p.CreateFunc(_T("MULT"), -1, mult);
  p.SetX(2);
  p.SetY(10);

  p.SetExpression("MULT(2,30)+x+y+1");
  cout << p.GetExpression() << endl; 
  cout << p.GetValue() << endl;

Floating Point Arithmetic Precision

Numerical computing has a known weakness with regard to precision of floating point numbers. There are overflows when you multiply or divide numbers and depending on your compiler settings, you may get errors or you may get wrong results. Here is the typical well known example where overflow occurs and the result varies in different systems (the result is wrong, and is not even close to the correct answer):

  cout << "-------------------------------------------------------" << endl;
  cout << "Following answer is wrong. It cannot be computed using double precision." << endl;
  cout << "A higher precision floating point library is needed." << endl;
  cout << "Use _DECIMAL support to compute it using MAPM library." << endl;
  try{
    //a^2-2ab+b^2 : 
    p.SetExpression("9876543210^2-2*9876543210*9876543211+9876543211^2");
    cout << p.GetExpression() << endl; 
    cout << p.GetValue() << endl;
  }catch(MathParser::ParserException &ex){
    cout << "Expected error: " << ex.GetMessage() << endl;
  }

Arbitrary Precision Arithmetic

To workaround these floating point arithmetic precision issues, there are arbitrary precision arithmetic libraries in C++. bcParserCPP is tested with and supports one such library MAPM. You can use _DECIMAL to start using MAPM to support arbitrary precision.

In general you may choose the desired numeric type by using a #define before you include MathParser.h:

//If you are going to use the parser with std::complex, then define this. 
#define _COMPLEX
//If you are going to use the parser with float, double, long double, then define this.
#define _DOUBLE
//If you are going to use the parser with a arbitrary precision decimal type such 
//as MAPM then define this. 
#define _DECIMAL

These defines affect what and how default functions and variables are implemented and defined. Other numeric types that are not covered by default may require changes to the default functions as well.

bcParserCPP Evaluation Download

bcParserCPP, the Math Parser for C++, is a C++ template that is defined in a header file. It is not a binary library. Therefore we cannot provide a binary that can be used to program to evaluate the parser. However, we do provide a simple command line calculator program where you can try the basics.

This is the entire source code for this calculator program:

#include 
#include "MathParser.h"

using namespace std;

//define a Math Parser that works with char strings for 
//variable and function names, and double values.
typedef CMathParser<char, double> MathParser;

int main(char **args){

try{
  MathParser p;

  string Expression;
  cout << "Input an expression such as x+sin(y) and press ENTER." << endl;
  cin >> Expression;
  cout << endl;

  p.SetExpression(Expression);

  if(p.IsVariableUsed("X")){
    cout << "Input X value and press ENTER." << endl; double x;
    cin >> x;
    cout << endl;
    p.SetX(x);
  }

  if(p.IsVariableUsed("Y")){
    cout << "Input Y value and press ENTER." << endl; double y;
    cin >> y;
    cout << endl;
    p.SetY(y);
  }

  cout << "-------------------------------------------------------" << endl;
  cout << "Result of " << p.GetExpression() << " is: " << p.GetValue() << endl;

  cout << "-------------------------------------------------------" << endl;
  cout << "Done." << endl;

  cin.ignore(256, '\n');
  cout << "Press ENTER to exit.";
  cin.get();
}catch(MathParser::ParserException &ex ){
  cout << ex.GetMessage() << endl;
  cout << "Invalid portion of expression is " << ex.GetInvalidPortionOfExpression() << endl;
}catch(...){
  cout << "Unexpected error in math parser." << endl;
}
}

Sample Calculator Download

Above sample 64 bit program is available for download for Linux, Mac OS X and Windows

os

 

Calculator for Mac OS X
Calculator for Linux
Calculator for Windows

When you run it, the command line calculator looks like this:

calc_cpp

bcParserCPP Documentation

The documentation for CMathParser template class is generated from the source code. You can view bcParserCPP documentation here.

bcParserCPP License

Licensing is per developer. Once you purchase the component, you can ship the binaries royalty free with your applications. The source code is provided because the library is a C++ template and also so that you can change to fit your needs. You may read the bcParserCPP license here.

Purchasing bcParserCPP – Math Parser for C++

You can pay with credit card and download bcParserCPP – Math Parser for C++ immediately from our online store for only $29.95. Upgrades are free for registered users. Licensing is per developer. You can deploy the the component royalty free with your applications as many times as you want . Site license (in online store) allows any number of developers use the component at your development site.

Online Order Form