www.pudn.com > Calculate20060802.rar > Calculate.cpp


#include "StdAfx.h" 
#include ".\Calculate.h" 
#include  
#include  
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& 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& 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 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::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 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::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; 
}