2KB项目,专业的源码交易网站 帮助 收藏 每日签到

CalcStar —— 一个 C++ 的数学表达式计算器

  • 时间:2019-01-23 18:36 编辑:2KB 来源:2KB.COM 阅读:377
  • 扫一扫,手机访问
  • 分享
摘要: 英文原文:Cal
英文原文:CalcStar: A C++ Math Expression Evaluator

介绍

CalcStar是一个可扩展的、快速的C++函数计算器,它有着像科学计算器一样强大的计算能力。它的库可以在任何C++工程中使用,提供函数计算功能。这个函数计算器将输入符号化并将其编译如你个RPN栈中,之后计算出结果返回给用户。式子用C++句式输入,并使用中缀表达式(例 2+2)。CalcStar支持带变量的式子。用下面的代码使用CalcStar的库函数。

#include <CalcStar.h>

然后,用户定义一个函数计算器,设定待计算表达式和变量,然后计算得到结果。当一个等式被计算后,用户可以重复利用现有的RPN栈来避免重复的计算。不过应当知道,计算其实是非常快的。下面是一个函数计算器到的使用实例,在源码中的TestApp中也可以找到。

Std::string strFunc;
strFunc = "(2 + 2)/3 * pow(3,2) - 2";
this->m_objFuncEvaluator.Set_strExpression(strFunc);
m_objFuncEvaluator.Evaluate();
dblAnswer = m_objFuncEvaluator.Get_dblCurrValue();

像这样简单地设置变量:

CSVariable objVarTemp;
objVarTemp.m_strVarName =
"X1";
objVarTemp.m_dblCurrVal =
varValue;
m_objFuncEvaluator.AddVariable(objVarTemp);

同样便利的变量赋值:

m_objFuncEvaluator.UpdateVariable(strVarName,
dblNewVal);

CalcStar设计

CalcStar是通用计算器。基本上他可以与任何中缀表达式科学计算器媲美(就像TI-83)。CalcStar计算表达式三步走:符号化、编译、执行。在符号化阶段,string中的数学表达式被转换成符号或数学语言。符号是数学表达式中的基本单元。下面是CalcStar中的符号(Token)类型:

enum CSTAR_DLLAPI CSTokenType
{ 
//IMPORTANT
NOTE!!! these operators are
// in order of
operation precedence
//THE LOWER THE
NUMBER THE HIGHER THE PRESCEDENCE
//DO NOT CHANGE
THIS ORDERING
//HARDCODING IS
USED BASED ON ENUMERATED TYPES
//
NOOP = -1,
OPENPAREN = 0, //Open
Parenthesis
OPENBRACKET, //Open
Bracket
OPENBLOCK, //Open
Block
CLOSEPAREN, //Close
Parenthesis
CLOSEBRACKET, //Close
Bracket
CLOSEBLOCK, //Close
Block
COMMA, //Comma
separator
NUMBER, //Number
VAR, //Variable
ASSIGN, //
= Assignment Operator
NEG, //
- Negative Operator
ADD, //
+ Addition Operator
SUB, //
- Subtraction Operator
MULT, //
* Multiplication Operator
DIV, //
/ Division Operator
LT, //
< Less Than Operator
GT, //
> Greater Than Operator
LTE, //
<= Less Than or Equal Operator
GTE, //
>= Greater Than or Equal Operator
NEQ, //
!= Not Equal To Boolean
EQ, //
== Equal To Boolean
AND, //
&& Logical And Boolean
OR, //
|| Logical Or Boolean
NOT, //
! Not Operator
FUNC //
Function
};

函数(Function)可以是任何类型的函数,可以被用户定义,例如aspow()是幂函数。函数的后面必须跟有"("。应当注意,如果CalcStar没有在已知函数中找到式子中的函数,它将把该函数标记是做一个变量。CSToken类有着下面这些成员变量:

//This is a thin class, so member
variables are public
//like in a typical struct
//!The token type of this RPN
Unit
CSTokenType m_objTokenType;
 
//!The string representation of
the token, also the signature
std::string m_strToken;
 
//!Token&apos;s associativity
CSAssociativity m_objAssociativity;
 
//!Numeric version of token if
applicable
double m_dblToken;

表达式被符号化后,就可以将其编译入逆波兰表达式(RPN)栈中,然后进行计算。使用Shunting Yard算法(一个计算机科学中的著名算法)创建RPN栈。RPN栈保存了运算顺序,并可以让计算机简单地通过扫描栈来计算式子。一个运算完成后,它的结果被保存为栈中单一的CSRpnUnit。不断执行该过程直到栈中只剩一个数字。这就是表达式的结果。

CalcStar表达式

用户可以输入任何可得出一个数的C++风格的中缀数学表达式。一个例子是:( 2 + 3) * X – 1,这里X是一个等于3.1415926的变量。唯一的危险是负数应当用括号括起来,例如(-2)。这将会在后续版本中解决。这个错误的原因是CalcStar将负号视作减号,而并没有将其视作数的一部分。在变量中必须保留负号,因为在编译时还不知道变量的值。另一个需要注意的是减号必须跟一个空格,否则将被视作负号。CalcStar内建的运算和函数如下:

Basic Functions
Name Signature Name Signature
Add + Boolean And &&
Subtract - Boolean Equal ==
Multiply * Boolean Not !
Divide / Boolean Not Equal !=
Exponential exp Boolean Or ||
Power pow Greater Than >
Natural Log ln Greater Than or Equal >=
Log2 log2 Less Than <
Log10 log10 Less Than or Equal <=
Absolute Value abs Ceiling ceil
Square Root sqrt Floor floor
Truncate trunc
Trigonometric Functions
Name Signature Name Signature
Sine sin Arc Sine asin
Cosine cos Arc Cosine acos
Tangent tan Arc Tangent atan
Hyp Sine sinh Arc Hyp Sine asinh
Hyp Cosine cosh Arc Hyp Cosine acosh
Hyp Tangent tanh Arc Hyp Tangent atanh

扩展CalcStar

CalcStar的一个重要特性是它是可扩展的。用户可以轻松地使用已有的运算和函数添加自定函数。每一个CSRpnUnit都有一个指向CSOpBase的指针,CSOpBase负责在Evaluate()被调用时执行运算。CSOpBase是所有运算和函数的基类。这是一个基本的伪函数设计,有一个虚函数:

virtual int OpEval(std::vector<CSRpnUnit> &
arrObjCalcStack, bool & blnCalcSuccessful,int intCurrPos) = 0;

该函数在被继承之后重载。我们可以从CSOpPower函数中一探究竟:

class CSOpPower: public CSOpBase
{
public:
//!Default Constructor
CSOpPower();
//!Default Destructor
~CSOpPower();
 
//!Perform
the operation on the stack
virtual int
OpEval(std::vector<CSRpnUnit> & arrObjCalcStack, bool &
blnCalcSuccessful,int intCurrPos);
 
};
 
//OBJECT FACTORY REGISTRATION CODE
static bool
blnCSOpPower_Registered = 
CSTAR::GetOpBaseFactoryPtr()->Register<CSOpPower>("pow");

CSOpPower继承自CSOpBase,并实现了虚函数OpEval来进行乘方计算。在定义了类之后,新的方法通过GetOpBaseFactoryPtr()…这行代码注册到OpBase工厂类。提供给函数的string是该函数的符号。像这样,用户想要注册一个新函数只要注册就可以了。当库文件被编译时,它会注册所有函数。 OpEval的实现:

//!Perform the operation on the stack
int CSOpPower::OpEval(std::vector<CSRpnUnit>
& arrObjCalcStack, bool &
blnCalcSuccessful,int intCurrPos)
{
//FUNCTION: pow(Number, numdecimal)
//first determine if the necessary inputs are valid, if they are,
//then get the input numbers and perform the calculation,
// Once the calculation is made
// then replace the operation and input tokens
// with the output number token
 
char chrOutput[256];
for (int i = 0; i < 256; chrOutput[i++] = &apos;&apos;);
blnCalcSuccessful = true;
bool blnValid;
double dblOutput;
CSRpnUnit
objOutput;
 
try{
this->ValidOpInputs(arrObjCalcStack,blnValid,intCurrPos,2);
 
if(blnValid)
{
//then valid inputs, perform the power calculation
//then replace the sin calculation results with the single number
double dblNum, dblPower;
this->GetOpNumber(&(arrObjCalcStack.at(intCurrPos - 1)),dblPower);
this->GetOpNumber(&(arrObjCalcStack.at(intCurrPos - 2)),dblNum);
 
dblOutput = pow(dblNum,dblPower);
 
objOutput.m_objTokenType = NUMBER;
objOutput.m_dblToken = dblOutput;
sprintf_s(chrOutput,"%f",dblOutput);
objOutput.m_strToken = chrOutput;
 
this->ReplaceOp(arrObjCalcStack,intCurrPos - 2,intCurrPos,objOutput);
blnCalcSuccessful = true;
return 1;
 
}else{
blnCalcSuccessful = false;
return 0;
}
}catch(...){
blnCalcSuccessful = false;
return -1;
}//end try
catch
 
};

这个运算首先调用aValidOpInputs()来检查输入的正确性。如果输入合法,就会执行乘方运算。接下来,ReplaceOp()会执行并将输入的数字和运算替换为一个输出数CSRpnUnit。建议用户也用采用这种模式(检查、计算、替换)。也推荐直接复制一个已有的函数,并改变它的名字和函数体来创建新函数。这比较简单,而且也不容易忘事或犯错。

本文中的所有译文仅用于学习和交流目的,转载请务必注明文章译者、出处、和本文链接。 2KB翻译工作遵照 CC 协议,如果我们的工作有侵犯到您的权益,请及时联系我们。


2KB项目(www.2kb.com,源码交易平台),提供担保交易、源码交易、虚拟商品、在家创业、在线创业、任务交易、网站设计、软件设计、网络兼职、站长交易、域名交易、链接买卖、网站交易、广告买卖、站长培训、建站美工等服务

  • 全部评论(0)
资讯详情页最新发布上方横幅
最新发布的资讯信息
【计算机/互联网|】Nginx出现502错误(2020-01-20 21:02)
【计算机/互联网|】网站运营全智能软手V0.1版发布(2020-01-20 12:16)
【计算机/互联网|】淘宝这是怎么了?(2020-01-19 19:15)
【行业动态|】谷歌关闭小米智能摄像头,因为窃听器显示了陌生人家中的照片(2020-01-15 09:42)
【行业动态|】据报道谷歌新闻终止了数字杂志,退还主动订阅(2020-01-15 09:39)
【行业动态|】康佳将OLED电视带到美国与LG和索尼竞争(2020-01-15 09:38)
【行业动态|】2020年最佳AV接收机(2020-01-15 09:35)
【行业动态|】2020年最佳流媒体设备:Roku,Apple TV,Firebar,Chromecast等(2020-01-15 09:31)
【行业动态|】CES 2020预览:更多的流媒体服务和订阅即将到来(2020-01-08 21:41)
【行业动态|】从埃隆·马斯克到杰夫·贝佐斯,这30位人物定义了2010年代(2020-01-01 15:14)
联系我们

Q Q: 7090832

电话:400-0011-990

邮箱:7090832@qq.com

时间:9:00-23:00

联系客服
商家入住 服务咨询 投拆建议 联系客服
0577-67068160
手机版

扫一扫进手机版
返回顶部