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

📄 calculate.cpp

📁 VC下最牛的算数表达式
💻 CPP
字号:
#include "StdAfx.h"
#include ".\Calculate.h"
#include <math.h>
#include <vector>
using namespace std;

int ExpressionItem::GetCalculation(bool bValue /*= false*/)	
{
	if(m_nFunction != -1)
	{
		int nIndex = m_strInput.Find('(');
		CString str = m_strInput.Mid(nIndex+1);
		// get the string between function parentheses
		str = str.Left(str.ReverseFind(')'));
		
		double u;
		int nError = Calculate(str, u);
		if(nError != 0 && bValue == true)
			return nError;
		if(nError == 0)
		{
			switch(m_nFunction)
			{
			case 13:	// asin
			case 14:	// acos
			case 16:	// asec
			case 17:	// acosec
				if(u < -1 || u > 1)
					return ERROR_INVALID_ARGUMENT;
				break;
			case 25:	// sqrt
			case 26:	// log10
			case 27:	// log
			case 28:	// ln
				if(u <= 0)
					return ERROR_INVALID_ARGUMENT;
				break;
			}
			switch(m_nFunction)
			{
				case 0:		m_nOutput = u;			break;		
				case 1:		m_nOutput = sin(u);		break;		
				case 2:		m_nOutput = cos(u);		break;
				case 3:		m_nOutput = tan(u);		break;
				case 4:		m_nOutput = cos(u);		break;	// sec
				case 5:		m_nOutput = sin(u);		break;	// cosec
				case 6:		m_nOutput = tan(u);		break;	// cot
				case 7:		m_nOutput = sinh(u);	break;		
				case 8:		m_nOutput = cosh(u);	break;		
				case 9:		m_nOutput = tanh(u);	break;		
				case 10:	m_nOutput = cosh(u);	break;	// sech
				case 11:	m_nOutput = sinh(u);	break;	// cosech
				case 12:	m_nOutput = tanh(u);	break;	// coth
				case 13:	m_nOutput = asin(u);	break;	
				case 14:	m_nOutput = acos(u);	break;	
				case 15:	m_nOutput = atan(u);	break;	
				case 16:	m_nOutput = acos(u);	break;	// asec
				case 17:	m_nOutput = asin(u);	break;	// acosec
				case 18:	m_nOutput = atan(u);	break;	// acot
				case 19:	str = asinh(str);		break;
				case 20:	str = acosh(str);		break;
				case 21:	str = atanh(str);		break;
				case 22:	str = asech(str);		break;
				case 23:	str = acosech(str);		break;
				case 24:	str = acoth(str);		break;
				case 25:	m_nOutput = sqrt(u);	break;	
				case 26:	m_nOutput = log10(u);	break;	
				case 27:	m_nOutput = log(u);		break;	
				case 28:	m_nOutput = log(u);		break;	
				case 29:	m_nOutput = sign(u);	break;	
				case 30:	m_nOutput = abs(u);		break;	
			}
			switch(m_nFunction)
			{
			case 4:		// sec
			case 5:		// cosec
			case 6:		// cot
			case 10:	// sech
			case 11:	// cosech
			case 12:	// coth
			case 16:	// asec
			case 17:	// acosec
			case 18:	// acot
				if(m_nOutput == 0)
					return ERROR_INVALID_ARGUMENT;
				m_nOutput = 1/m_nOutput;
				break;
			case 19:	// asinh
			case 20:	// acosh
			case 21:	// atanh
			case 22:	// asech
			case 23:	// acosech
			case 24:	// acoth
				if((nError = Calculate(str, m_nOutput)) < 0)
					return nError;
				break;
			}
			m_nOutput *= m_nSign; 
			m_strOutput = TrimFloat(m_nOutput);
		}
		else
		{
			if(m_nFunction == -1 && bValue == true)
				return ERROR_NOT_NUMERIC;
			switch(m_nFunction)
			{
			case 0:		m_strOutput = c(str, m_strStack);			break;
			case 1:		m_strOutput = c_sin(str, m_strStack);		break;		
			case 2:		m_strOutput = c_cos(str, m_strStack);		break;
			case 3:		m_strOutput = c_tan(str, m_strStack);		break;
			case 4:		m_strOutput = c_sec(str, m_strStack);		break;
			case 5:		m_strOutput = c_cosec(str, m_strStack);		break;
			case 6:		m_strOutput = c_cot(str, m_strStack);		break;		
			case 7:		m_strOutput = c_sinh(str, m_strStack);		break;	
			case 8:		m_strOutput = c_cosh(str, m_strStack);		break;	
			case 9:		m_strOutput = c_tanh(str, m_strStack);		break;	
			case 10:	m_strOutput = c_sech(str, m_strStack);		break;	
			case 11:	m_strOutput = c_cosech(str, m_strStack);	break;	
			case 12:	m_strOutput = c_coth(str, m_strStack);		break;	
			case 13:	m_strOutput = c_asin(str, m_strStack);		break;	
			case 14:	m_strOutput = c_acos(str, m_strStack);		break;	
			case 15:	m_strOutput = c_atan(str, m_strStack);		break;	
			case 16:	m_strOutput = c_asec(str, m_strStack);		break;	
			case 17:	m_strOutput = c_acosec(str, m_strStack);	break;	
			case 18:	m_strOutput = c_acot(str, m_strStack);		break;	
			case 19:	m_strOutput = c_asinh(str, m_strStack);		break;	
			case 20:	m_strOutput = c_acosh(str, m_strStack);		break;	
			case 21:	m_strOutput = c_atanh(str, m_strStack);		break;	
			case 22:	m_strOutput = c_asech(str, m_strStack);		break;	
			case 23:	m_strOutput = c_acosech(str, m_strStack);	break;	
			case 24:	m_strOutput = c_acoth(str, m_strStack);		break;	
			case 25:	m_strOutput = c_sqrt(str, m_strStack);		break;	
			case 26:	m_strOutput = c_log10(str, m_strStack);		break;
			case 27:	m_strOutput = c_log(str, m_strStack);		break;
			case 28:	m_strOutput = c_ln(str, m_strStack);		break;
			case 29:	m_strOutput = c_sign(str, m_strStack);		break;
			case 30:	m_strOutput = c_abs(str, m_strStack);		break;
			}
			m_nOutput = m_nSign*ATOF(m_strOutput);
			m_strOutput = (m_nSign == -1?"-":"")+m_strOutput;
			if(bValue == true && IsNumeric(m_strOutput) == false)
			{
				m_strStack.Empty();
				return ERROR_NOT_NUMERIC;
			}
		}
	}
	else
	{
		m_strOutput = m_strInput;
		if(bValue && IsNumeric(m_strOutput) == false)
		{
			m_strStack.Empty();
			return ERROR_NOT_NUMERIC;
		}
		m_nOutput = ATOF(m_strOutput);
	}

	return 0;
}

char* GetErrorMessage(int nError)
{
	switch(nError)
	{
	case ERROR_INVALID_ARGUMENT:
		return "Invalid argument";
	case ERROR_NOT_NUMERIC:
		return "Not numeric";
	case ERROR_DIVIDE_BY_ZERO:
		return "Divide by zero";
	}
	return "Unknow error";
}

int CalculateStack(vector<ExpressionItem*>& vStack, int& nExpression, CString& strOutput)
{
	ExpressionItem *pQI = vStack[nExpression++];
	int nError;
	if(pQI->m_cOperator)
	{
		CString cu, cv;
		// get left operand calculation
		if((nError = CalculateStack(vStack, nExpression, cu)) < 0)
			return nError;
		// get right operand calculation
		if((nError = CalculateStack(vStack, nExpression, cv)) < 0)
			return nError;

		if(IsNumeric(cu) == false || IsNumeric(cv) == false)
		{
			switch(pQI->m_cOperator)
			{
				case '-':	// c(u-v) = cu-cv
				case '+':	// c(u+v) = cu+cv
					pQI->m_strOutput = cu+pQI->m_cOperator+cv;
					break;
				case '*':	// c(u*v) = cu*cv
					pQI->m_strOutput = cu+'*'+cv;
					break;
				case '/':	// c(u/v) = cu/cv
					pQI->m_strOutput = cu+'/'+cv;
					break;
				case '^':	// c(u^v) = cu^cv
					pQI->m_strOutput = cu+'^'+cv;
					break;
				case '%':	// c(u%v) = cu%cv
					pQI->m_strOutput = cu+'%'+cv;
					break;
			}
			pQI->m_strOutput = '('+pQI->m_strOutput+')';
		}
		else
			switch(pQI->m_cOperator)
			{
				case '-':	// c(u-v) = cu-cv
					pQI->m_strOutput.Format("%s", TrimFloat(ATOF(cu)-ATOF(cv)));
					break;
				case '+':	// c(u+v) = cu+cv
					pQI->m_strOutput.Format("%s", TrimFloat(ATOF(cu)+ATOF(cv)));
					break;
				case '*':	// c(u*v) = cu*cv
					pQI->m_strOutput.Format("%s", TrimFloat(ATOF(cu)*ATOF(cv)));
					break;
				case '/':	// c(u/v) = cu/cv
					if(ATOF(cv) == 0)
						return ERROR_DIVIDE_BY_ZERO;
					pQI->m_strOutput.Format("%s", TrimFloat(ATOF(cu)/ATOF(cv)));
					break;
				case '^':	// c(u^v) = cu^cv
					pQI->m_strOutput.Format("%s", TrimFloat(pow(ATOF(cu), ATOF(cv))));
					break;
				case '%':	// c(u%v) = cu%cv
					pQI->m_strOutput.Format("%s", TrimFloat((int)ATOF(cu)%(int)ATOF(cv)));
					break;
			}
	}
	else
		// get Expression calculation
		if((nError = pQI->GetCalculation(false)) < 0)
		{
			strOutput = GetErrorMessage(nError);
			return nError;
		}
	// return resultant calculation
	strOutput =  pQI->m_strOutput;
	
	return 0;
}

int CalculateStack(vector<ExpressionItem*>& vStack, int& nExpression, double& dOutput)
{
	ExpressionItem *pQI = vStack[nExpression++];
	int nError;
	if(pQI->m_cOperator)
	{
		double cu, cv;
		// get left operand calculation
		if((nError = CalculateStack(vStack, nExpression, cu)) < 0)
			return nError;
		// get right operand calculation
		if((nError = CalculateStack(vStack, nExpression, cv)) < 0)
			return nError;

		switch(pQI->m_cOperator)
		{
			case '-':	// c(u-v) = cu-cv
				pQI->m_nOutput = cu-cv;
				break;
			case '+':	// c(u+v) = cu+cv
				pQI->m_nOutput = cu+cv;
				break;
			case '*':	// c(u*v) = cu*cv
				pQI->m_nOutput = cu*cv;
				break;
			case '/':	// c(u/v) = cu/cv
				if(cv == 0)
					return ERROR_DIVIDE_BY_ZERO;
				pQI->m_nOutput = cu/cv;
				break;
			case '^':	// d(u^v) = cu^cv
				if(cu < 0 && (int)cv != (double)cv)
					return ERROR_INVALID_ARGUMENT;
				pQI->m_nOutput = pow(cu, cv);
				break;
			case '%':	// d(u%v) = cu%cv
				pQI->m_nOutput = (int)cu%(int)cv;
				break;
		}
	}
	else
		// get Expression calculation
		if((nError = pQI->GetCalculation(true)) < 0)
			return nError;
	// return resultant calculation
	dOutput = pQI->m_nOutput;

	return 0;
}

int Calculate(LPCSTR lpcsInput, double& dOutput)
{
	CString strInput = lpcsInput;
	// remove spaces
	strInput.Remove(' ');
	// make all characters lower case
	strInput.MakeLower();
	// Optimize "--"
	OptimizeSign(strInput);

	int nError;
	vector<ExpressionItem*> vStack;
	// parse input equation and fill stack with operators and operands
	if((nError = FillStack(strInput, vStack)) < 0)
		return nError;

	int nExpression = 0;
	// apply operators to operands
	nError = CalculateStack(vStack, nExpression, dOutput);
	for(vector<ExpressionItem*>::iterator pQI = vStack.begin(); pQI != vStack.end(); pQI++)
		delete *pQI;
	return nError;
}

CString Calculate(LPCSTR lpcsInput, CString& strStack, bool bOptimize)
{
	CString strInput = lpcsInput;
	// remove spaces
	strInput.Remove(' ');
	// make all characters lower case
	strInput.MakeLower();
	// Optimize "--"
	OptimizeSign(strInput);

	int nError;
	vector<ExpressionItem*> vStack;
	// parse input equation and fill stack with operators and operands
	if((nError = FillStack(strInput, vStack)) < 0)
		return GetErrorMessage(nError);

	CString strOutput;
	double nOutput;
	int nExpression = 0;
	// apply operators to operands
	if(CalculateStack(vStack, nExpression, nOutput) < 0)
	{			   
		nExpression = 0;
		// apply operators to operands
		CalculateStack(vStack, nExpression, strOutput);
	}
	else
		strOutput = TrimFloat(nOutput);

	// loop to fill the stack string from the stack vector
	for(vector<ExpressionItem*>::iterator pQI = vStack.begin(); pQI != vStack.end(); pQI++)
	{
		if((*pQI)->m_cOperator)
			strStack += (*pQI)->m_cOperator + CString("\r\n");
		else
			strStack += "c("+(*pQI)->m_strInput+") = "+(*pQI)->m_strOutput+"\r\n";

		// insert tabs in front of the item stack
		InsertTabs((*pQI)->m_strStack);
		strStack += (*pQI)->m_strStack;
		delete *pQI;
	}

	if(bOptimize == true)
		// optimize the equation from unneeded elements
		Optimize(strOutput);
	// return output calculation
	return strOutput;
}

⌨️ 快捷键说明

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