📄 calculate.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 + -