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; }