⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 funcs.cpp

📁 一个解析数学表达式的c++程序
💻 CPP
字号:
#include "Funcs.h"
#include <float.h>
#include <math.h>

#include "..\..\..\MTParserLib\MTTools.h"

//*************************************
// DerivativeFct

#define DERIVATE_H		0.0001
#define DERIVATE_2H		0.0002
#define DERIVATE_12H	0.0012


DerivativeFct::DerivativeFct()
{
	m_pExpr = NULL;
}

DerivativeFct::~DerivativeFct()
{
	clean();	
}

void DerivativeFct::clean()
{
	if( m_pExpr != NULL )
	{
		delete m_pExpr;
		m_pExpr = NULL;
	}
}

MTDOUBLE DerivativeFct::evaluate(unsigned int nbArgs, const MTDOUBLE *pArg)
{ 		
	// f'(pt) = ( -f(pt+2h)+8f(pt+h)-8f(pt-h)+f(pt-2h) )/(12h)
	
	double pt = pArg[0];
	
	m_ptVal = pt+DERIVATE_2H;
	double f2h = m_pExpr->evaluate();

	m_ptVal = pt+DERIVATE_H;
	double fh = m_pExpr->evaluate();

	m_ptVal = pt-DERIVATE_H;
	double fmh = m_pExpr->evaluate();

	m_ptVal = pt-DERIVATE_2H;
	double fm2h = m_pExpr->evaluate();

	return (-f2h + 8.0*fh - 8.0*fmh + fm2h) / DERIVATE_12H;		
}

bool DerivativeFct::isConstant()
{
	// if only one var used, this is the local iterator
	return m_pExpr->getNbUsedVars() == 1;
}

void DerivativeFct::init(std::vector<MTSTRING> params, MTCompilerI *pCompiler, MTRegistrarI *pRegistrar, unsigned int pos) throw(MTParserException)
{
	clean();

	// param 0:		expression
	// param 1:		variable's name
	// param 2:		point

	if( params.size() != 3 )
	{
		// invalid number of arguments!
		pCompiler->throwParsingExcep(MTPARSINGEXCEP_OverloadedFuncNotFound, pos, getSymbol(), params.size());		
	}

	m_pExpr = new MTParser(pCompiler, pRegistrar);
	
	m_pExpr->getCompiler()->setParent(pCompiler);			
	// force variables to be defined by the parent...
	m_pExpr->enableAutoVarDefinition(false);
	m_pExpr->undefineAllVars();
	
	int argNumber;	
	try
	{	
		// begin by defining the variable in order to be able to compile
		argNumber = 2;
		m_pExpr->defineVar(params[1].c_str(), &m_ptVal);

		argNumber = 1;
		m_pExpr->compile(params[0].c_str());

		argNumber = 3;
		pCompiler->pushFuncArg(params[2].c_str());
	}
	catch(MTParserException &e)
	{				
		
		MTRETHROW( MTExcepData(	MTPARSINGEXCEP_InvalidFuncSyntax,
								MTEXCEPARG_ITEMNAME, getSymbol(),
								MTEXCEPARG_POS, MTTools::longToS(pos).c_str(),
								MTEXCEPARG_PARAM1, MTTools::longToS(argNumber).c_str()),
								e)
	}		
}

MTFunctionI* DerivativeFct::spawn()
{ 
	return new DerivativeFct(); 
}

//*************************************
// TrapezoidFct

TrapezoidFct::TrapezoidFct()
{
	m_pExpr = NULL;	
}

TrapezoidFct::~TrapezoidFct()
{
	clean();	
}

void TrapezoidFct::clean()
{
	if( m_pExpr != NULL )
	{
		delete m_pExpr;
		m_pExpr = NULL;
	}
}

MTDOUBLE TrapezoidFct::evaluate(unsigned int nbArgs, const MTDOUBLE *pArg)
{ 		

	double a = pArg[0];
	double b = pArg[1];	
	double step = fabs(pArg[2]);		// make sure to take a positive number
	double stepd2 = step / 2.0;

	if( step == 0 )
	{
		return 0;	// avoid infinite loop!
	}

	// make sure that b is greater than a
	if( a > b )
	{
		double t = a;
		a = b;
		b = t;
	}
	
	m_ptVal = a;

	double lastPt = m_pExpr->evaluate();
	double curPt;
	double curPos = a+step;
	double res = 0;	

	while( curPos <= b )
	{
		m_ptVal = curPos;
		curPt = m_pExpr->evaluate();		
		res += (lastPt+curPt)*stepd2;
		lastPt = curPt;
		curPos += step;
	}

	return res;	
}

bool TrapezoidFct::isConstant()
{
	return m_pExpr->getNbUsedVars() == 1;
}

void TrapezoidFct::init(std::vector<MTSTRING> params, MTCompilerI *pCompiler, MTRegistrarI *pRegistrar, unsigned int pos) throw(MTParserException)
{
	clean();

	// param 0	expression
	// param 1	variable's name
	// param 2	first point
	// param 3	second point
	// param 4	step (optional)

	if( params.size() != 4 && params.size() != 5)
	{
		// invalid number of arguments!
		pCompiler->throwParsingExcep(MTPARSINGEXCEP_OverloadedFuncNotFound, pos, getSymbol(), params.size());		
	}

	MTSTRING precision = MTTools::doubleToS(0.1, pRegistrar->getSyntax().decimalPoint,1);
	if( params.size() == 5 )
	{
		precision = params[4];
	}

	m_pExpr = new MTParser(pCompiler, pRegistrar);
	
	m_pExpr->getCompiler()->setParent(pCompiler);			
	// force variables to be defined by the parent...
	m_pExpr->enableAutoVarDefinition(false);
	m_pExpr->undefineAllVars();

	
	int argNumber;	
	try
	{	
		
		argNumber = 2;
		// begin by defining the variable in order to be able to compile
		// define the variable locally, pointing to our member variable
		m_pExpr->defineVar(params[1].c_str(), &m_ptVal);

		argNumber = 1;
		m_pExpr->compile(params[0].c_str());

		argNumber = 3;
		pCompiler->pushFuncArg(params[2].c_str());		

		argNumber = 4;
		pCompiler->pushFuncArg(params[3].c_str());		

		argNumber = 5;
		pCompiler->pushFuncArg(precision.c_str());

	}
	catch(MTParserException &e)
	{		

		MTRETHROW( MTExcepData(	MTPARSINGEXCEP_InvalidFuncSyntax,
								MTEXCEPARG_ITEMNAME, getSymbol(),
								MTEXCEPARG_POS, MTTools::longToS(pos).c_str(),
								MTEXCEPARG_PARAM1, MTTools::longToS(argNumber).c_str()),
								e)
	}			
}


MTFunctionI* TrapezoidFct::spawn()
{ 
	return new TrapezoidFct(); 
}

//*************************************
// SolveFct

SolveFct::SolveFct()
{
	m_pExpr = NULL;	
}

SolveFct::~SolveFct()
{
	clean();	
}

void SolveFct::clean()
{
	if( m_pExpr != NULL )
	{
		delete m_pExpr;
		m_pExpr = NULL;
	}
}

inline double SolveFct::d1(double pt)
{
	m_ptVal = pt+DERIVATE_2H;
	double f2h = m_pExpr->evaluate();

	m_ptVal = pt+DERIVATE_H;
	double fh = m_pExpr->evaluate();

	m_ptVal = pt-DERIVATE_H;
	double fmh = m_pExpr->evaluate();

	m_ptVal = pt-DERIVATE_2H;
	double fm2h = m_pExpr->evaluate();

	return (-f2h + 8.0*fh - 8.0*fmh + fm2h) / DERIVATE_12H;		
}

inline double SolveFct::d2(double pt)
{	
	double f2h = d1(pt+DERIVATE_2H);
	double fh = d1(pt+DERIVATE_H);
	double fmh = d1(pt-DERIVATE_H);	
	double fm2h = d1(pt-DERIVATE_2H);

	return (-f2h + 8.0*fh - 8.0*fmh + fm2h) / DERIVATE_12H;	
}

MTDOUBLE SolveFct::evaluate(unsigned int nbArgs, const MTDOUBLE *pArg)
{ 		

	double tol = pArg[2];
	int maxIter = (int)pArg[3];

	if( maxIter <= 0 )
	{
		return 0;
	}

	double exprVal = pArg[0];
	double xold = pArg[1];
	double xnew = 0;
	double fVal, d1fVal, d2fVal;
	double err = tol+1;		// current error
	double fValOnd1fVal;	// fVal/d1fVal
	int t = 0;				// iteration counter


	// Newton's algorithm tries to find one zero
	// The expression we solve is: expr-val=0

	while( t<maxIter && err > tol )
	{
		m_ptVal = xold;
		fVal = m_pExpr->evaluate()-exprVal;

		d1fVal = d1(xold);

		// the first derivate must not be too small, otherwise the
		// algorithm will explode
		if( fabs(d1fVal) > DERIVATE_H )
		{				
			d2fVal = d2(xold);
			fValOnd1fVal = fVal/d1fVal;

			xnew = xold - fValOnd1fVal - 0.5*d2fVal/d1fVal * pow(fValOnd1fVal,2);

			err = fabs( xnew - xold );
			xold = xnew;
		}
		else
		{
			xold += 1;		// try to move out of this hole!
		}

		t++;
	}

	return xnew;	
}

bool SolveFct::isConstant()
{
	return m_pExpr->getNbUsedVars() == 1;
}

void SolveFct::init(std::vector<MTSTRING> params, MTCompilerI *pCompiler, MTRegistrarI *pRegistrar, unsigned int pos) throw(MTParserException)
{
	clean();	
	
	// param 0	expression
	// param 1	variable's name
	// param 2	expression's value
	// param 3	initial approximation (optional)
	// param 4	tolerance (optional)
	// param 5	maxIteration (optional)

	if( params.size() < 3 || params.size() > 6)
	{
		// invalid number of arguments!
		pCompiler->throwParsingExcep(MTPARSINGEXCEP_OverloadedFuncNotFound, pos, getSymbol(), params.size());		
	}	

	MTSTRING v0 = _T("0");
	MTSTRING tol = MTTools::doubleToS(0.01, pRegistrar->getSyntax().decimalPoint,2);
	MTSTRING maxIter = _T("100");	

	if( params.size() >= 4 )
	{
		v0 = params[3];
		if( params.size() >= 5 )
		{
			tol = params[4];

			if( params.size() == 6 )
			{
				maxIter = params[5];
			}
		}
	}	

	m_pExpr = new MTParser(pCompiler, pRegistrar);
	
	m_pExpr->undefineAllVars();
	// force variables to be defined by the parent...
	m_pExpr->enableAutoVarDefinition(false);
	m_pExpr->getCompiler()->setParent(pCompiler);			
	
	int argNumber;	
	try
	{			
		argNumber = 2;
		// begin by defining the variable in order to be able to compile
		// define the variable locally, pointing to our member variable
		m_pExpr->defineVar(params[1].c_str(), &m_ptVal);	

		argNumber = 1;
		m_pExpr->compile(params[0].c_str());			

		argNumber = 3;
		pCompiler->pushFuncArg(params[2].c_str());			

		argNumber = 4;
		pCompiler->pushFuncArg(v0.c_str());				

		argNumber = 5;
		pCompiler->pushFuncArg(tol.c_str());			

		argNumber = 6;
		pCompiler->pushFuncArg(maxIter.c_str());		
	}
	catch(MTParserException &e)
	{				

		MTRETHROW( MTExcepData(	MTPARSINGEXCEP_InvalidFuncSyntax,
								MTEXCEPARG_ITEMNAME, getSymbol(),
								MTEXCEPARG_POS, MTTools::longToS(pos).c_str(),
								MTEXCEPARG_PARAM1, MTTools::longToS(argNumber).c_str()),
								e)
	}	
}

MTFunctionI* SolveFct::spawn()
{ 
	return new SolveFct(); 
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -