13,596,556 members
alternative version

#### Stats

69.6K views
49 bookmarked
Posted 26 Apr 2004
Licenced CPOL

# Simple(x) Numerical Formula Parser

, 26 Apr 2004
Numerical Formula class from the SimplexParser freeware

## Introduction

I'd like to set up my numerical formula class from SimplexParser in addition to my previous article about the date & time math parser (see here) also to the CodeProject site. With the class `CFormulaParser `you can parse and evaluate numerical expressions and functions with variables given in a string. The class encapsulates also a useful mathematical parser for physical constants.

The demo project has the following simple input dialog for formula/function and variable/constants.

## Sample Operations

The parser interprets editors code like:

Function: `f(x) = y = sin(x)/x + a`

whereby x is the main variable and a - h are the constants in the function. The result will be shown in the output window when you press the Enter button. That you can save and load the function and constants is in fact not so important here.

## `CFormulaParser `class

The following code shows the main methods from the `CFormulaParser `class:

```//...

class CFormulaParser
{
private:
// Physical Constants
CPhysConst m_PhysConst;

//Implementation
CString m_strFormula;
CString m_strFunction;
CString m_strErrortext;

static CString g_strF;

double m_dFktValue;
double m_dFunctionConstant[ANZFUNKTKONST];
CStringArray m_strStandardFunction;

double SignFactor(int& nPosition, CString& strCharacter);
double Expression(int& nPosition, CString& strCharacter);
double SimpleExpression(int& nPosition, CString& strCharacter);
double Term(int& nPosition, CString& strCharacter);
double Factor(int& nPosition, CString& strCharacter);
double Char_n(int& nPosition, CString& strCharacter);
CString strChar_(BYTE DecimalZahl);

CString GetNextToken(CString& strSrc, const CString strDelim);

double DEG(double x /* rad */) ;
double cot(double x);
long double signl(long double x);
double ArSinh(double x);
double ArCosh(double x);
double ArTanh(double x);
double ArCoth(double x);
double sqr(double x);

public:
void StripFormula(CString& strFormula);
CString GetFormula();
void SetFormula(CString Formula);
void SetFunctConst(int index, double val);

CFormulaParser();
virtual ~CFormulaParser();

//Interface
double Calculation(CString strFormula, double xValue,
int& nErrorPosition, CString& strErrortext, BOOL strip = true);
};

//...```

## Using the code

The main method in `CFormulaParser `for the evaluation is:

```double Calculation(CString strFormula,
double xValue, int& nErrorPosition,
CString& strErrortext, BOOL strip = true);```

where

• `strFormula` is the formula string, e.g. "b*sin(x)/x"
• `xValue` is in this case x, e.g. 0.0123
• `nErrorPosition` gives back the error position in the string
• `strErrortext` gives back the corresponding error text

You can use this code as shown next:

```//...

void CSimplexParserDlg::OnEnter()
{
int ErrorPosition;
char buffer[64];
CString strErrortext;
strErrortext.Empty();

UpdateData(true);

//___________________________
CFormulaParser FormulaParser;
//___________________________

FormulaParser.SetFunctConst(1, m_dKonstA);
FormulaParser.SetFunctConst(2, m_dKonstB);
FormulaParser.SetFunctConst(3, m_dKonstC);
FormulaParser.SetFunctConst(4, m_dKonstD);
FormulaParser.SetFunctConst(5, m_dKonstE);
FormulaParser.SetFunctConst(6, m_dKonstF);
FormulaParser.SetFunctConst(7, m_dKonstG);
FormulaParser.SetFunctConst(8, m_dKonstH);

//______________________________________________
double retValue = FormulaParser.Calculation(m_strFormulainput,
m_dKonstX, ErrorPosition, Errortext);
//______________________________________________

CWnd* pWnd = GetDlgItem(IDC_FORMULAINPUT);
pWnd->SetFocus();
if (nErrorPosition == 0)
{
if (strErrortext == "")
{
sprintf(buffer, "%f", retValue);
m_strFormulaoutput = buffer;
}
else
m_strFormulaoutput = "Error: " + Errortext;

pWnd->SendMessage(EM_SETSEL,32767,32767);
}
else
{
m_strFormulaoutput = strErrortext;
pWnd->SendMessage(EM_SETSEL,nErrorPosition - 1,nErrorPosition);
}

UpdateData(false);
}

//...```

## Physical Constants

The class encapsulates also a useful mathematical parser for physical constants. The implementation of the Physical Constants is very simple to use.

Define in the file PhysConst.h some additional constants like

```// Velocity of light in vacuum (def) m/s
const double _c = 2.99792458E8;

// Planck constant (40)J s
const double _h = 6.6260755E-34;

// etc.```

with a underline symbol in front (e.g. `_abcd`). The name must be unique under the names.

Then fill in the constructor and member functions in the class `CPhysConst`:

```//...

class CPhysConst
{
public:
CPhysConst();
virtual ~CPhysConst();

public:
//Functions
BOOL IsPhysConst(CString str);
double GetPhysConstValue(const CString str);
CString GetEachPhysConst(int i);
void SetPhysConstOrder();

private:
// String Array
CStringArray m_strPhysConst;
};

//...```

like this:

```//...
// constructor

CPhysConst::CPhysConst()
{
// ...

//...```

and this:

```//...
BOOL CPhysConst::IsPhysConst(CString str)
{
if (stricmp(str, _T("_c")) == 0) return true;
if (stricmp(str, _T("_h")) == 0) return true;

//...```

and finally this one:

```//...
double CPhysConst::GetPhysConstValue(const CString str)
{
if (stricmp(str, _T("_c")) == 0) return _c;
if (stricmp(str, _T("_h")) == 0) return _h;

//...```

You can use this code as shown next:

```//...

CPhysConst m_PhysConst;

//...
else if (strFunctionUpper == "ARCOSH")
{
if (fabs(f) >= 1)
f = ArCosh(f);
else
wError = -1;
}
else if (strFunctionUpper == "ARTANH")
{
if (fabs(f) <= 1)
f = ArTanh(f);
else
wError = -1;
}
else if (double pc = m_PhysConst.GetPhysConstValue(strFunctionUpper))
{
f = pc;
}
break;
}

//...```

I hope that the code is reasonably obvious how to use. Look to the demo project for more details.

## History

• 1.0 (25 April 2004) Initial Release

## Acknowledgement

This would not have been possible without all the authors making their code freely available! So, thanks for that, SimplexParser will be available as freeware for all the time.

## Share

 Software Developer (Senior) Germany
Ralf is the programmer of the well-known programs SimplexNumerica and SimplexParser. He's been programming since 1986 since he was at the Fraunhofer Institute for Laser Technology (ILT) in Aachen/Germany. His preferred programming language is Visual C++ with MFC/ATL and GFA Basic. Ralf was born near Gerolstein/Germany. He went to Aachen University where he obtained a Diploma of technical physics. He works as a senior design engineer for a fairly large, international company.

## You may also be interested in...

 First Prev Next
 Nice Article Suvabrata Roy17-Jul-12 3:16 Suvabrata Roy 17-Jul-12 3:16
 Re: Nice Article Ralf Wirtz17-Jul-12 7:50 Ralf Wirtz 17-Jul-12 7:50
 Re: Nice Article Suvabrata Roy17-Jul-12 18:56 Suvabrata Roy 17-Jul-12 18:56
 I have a problem to use your code. jrgemini26-Mar-09 15:51 jrgemini 26-Mar-09 15:51
 Very good Job! LoganKale31-May-06 10:04 LoganKale 31-May-06 10:04
 Re: Very good Job! Anders Gustafsson14-Dec-07 23:57 Anders Gustafsson 14-Dec-07 23:57
 Same problem here Anonymous10-Aug-05 1:52 Anonymous 10-Aug-05 1:52
 very good zxaar12-Dec-04 17:01 zxaar 12-Dec-04 17:01
 Perfect Obliterator4-Nov-04 6:57 Obliterator 4-Nov-04 6:57
 Nice work! John R. Shaw6-May-04 8:19 John R. Shaw 6-May-04 8:19
 Last Visit: 31-Dec-99 18:00     Last Update: 23-Jun-18 5:07 Refresh 1