Click here to Skip to main content
15,886,519 members
Articles / Programming Languages / C++
Article

Simple(x) Numerical Formula Parser

Rate me:
Please Sign up or sign in to vote.
4.81/5 (27 votes)
26 Apr 2004CPOL2 min read 83.1K   4.7K   53   13
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.

Image 1

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

Image 2

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 SINQ(double Winkel_grad);
  double COSQ(double Winkel_grad);
  double DEG(double x /* rad */) ;
  double RAD(double x /* grad */);
  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()
{
  // ...
  m_strPhysConst.Add(_T("_c"));
  m_strPhysConst.Add(_T("_h"));

//...

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.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer (Senior)
Germany 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.

Comments and Discussions

 
QuestionThanks Pin
Member 1414623611-Feb-19 23:34
Member 1414623611-Feb-19 23:34 
GeneralNice Article Pin
Suvabrata Roy17-Jul-12 3:16
professionalSuvabrata Roy17-Jul-12 3:16 
GeneralRe: Nice Article Pin
Ralf Wirtz17-Jul-12 7:50
Ralf Wirtz17-Jul-12 7:50 
GeneralRe: Nice Article Pin
Suvabrata Roy17-Jul-12 18:56
professionalSuvabrata Roy17-Jul-12 18:56 
QuestionPerfect but... [modified] Pin
gladju018-Jul-11 11:32
gladju018-Jul-11 11:32 
QuestionI have a problem to use your code. Pin
jrgemini26-Mar-09 15:51
jrgemini26-Mar-09 15:51 
GeneralVery good Job! Pin
LoganKale31-May-06 10:04
LoganKale31-May-06 10:04 
GeneralRe: Very good Job! Pin
Anders Gustafsson14-Dec-07 23:57
Anders Gustafsson14-Dec-07 23:57 
GeneralSame problem here Pin
Anonymous10-Aug-05 1:52
Anonymous10-Aug-05 1:52 
Generalvery good Pin
zxaar12-Dec-04 17:01
zxaar12-Dec-04 17:01 
GeneralPerfect Pin
Obliterator4-Nov-04 6:57
Obliterator4-Nov-04 6:57 
GeneralNice work! Pin
John R. Shaw6-May-04 8:19
John R. Shaw6-May-04 8:19 

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

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