C#实现复杂表达式的计算

C#实现复杂表达式的计算

1、问题描述:
设计一个能进行+ - * /,同时支持sin、cos、abs等函数的计算器,对于表达式中未声明的变量,随机生成一个0~9的数,其中x是默认变量。
例如:
1)、-1+a+0.12
2)、asin(bx+c)
3)、asin(b*x+c^2)+abs(3+x)/(s*floor(x))+a

2、解决思路:
拆分与标准化表达式------》计算表达式的值-------》得出结果

首先
将表达式看成是由若干Item项之和构成的,即:
Expression=Item1+Item2+…+Itemn
其中,Item由若干个因子Factor的乘积或商构成。
Factor可以是常数、变量、运算函数、带括号的表达式。

表达式拆分的解决策略:
设置一个变量couples用来记录当前检索到的未成对括号的对数,初始值为0;当couples=0且当前检索的字符temp=’+‘或者temp=’-'时,就表示是一个Item项的结束,将此前已检索的字符串赋给Item,同时置另一个Item项的初值为temp,即Item+=temp;以此进行下去,直至检索结束。最后一个Item项的值为结束前已检索的字符串。
例如:
表达式asin(b*x+c^2)+abs(3+x)/(s*floor(x))+a拆分后得
Item1=asin(b*x+c^2)
Item2=+abs(3+x)/(s*floor(x))
Item3=+a

其次
将每个Item项标准化,例如Item项asin(bx+c),标准化后a*sin(b*x+c)。
标准化时,默认一连串字母中在最后才有可能出现运算函数,此时采用的策略是循环匹配,若匹配成功则表明这一连串字母代表一个运算函数,否则,这一连串字母中的第一个是变量,剩下的字母再进行,直至匹配成功或剩下字母的个数为零。
当遇到表达式(1+2)(1+3),标准化后(1+2)*(1+3)。即当前字符为),且下一个字符为(时,要在中间添加一个*。

最后
计算每一个Item项的值,最后将每个Item项的值相加。

每一个item项的计算:用栈来实现
将Item项中数值与运算符分别压入数据栈和运算符栈中,将运算符压入运算符栈中需注意:
(1)、若栈为空,则直接将运算符压入
(2)、若栈不为空,且将要压入的元素为+或者-,则依次将运算符退栈并取出数据栈的所需元素个数进行相应的运算同时将运算结果压入数据栈中,直至运算符栈为空。
(3)、若栈不为空,且将要压入的元素为*、/,则依次将运算符退栈并取出数据栈的所需元素个数进行相应的运算同时将运算结果压入数据栈中,直至运算符栈为空或者栈顶元素为+或者-。
(4)、若栈不为空,且将要压入的元素为^或者sin等运算函数,则依次将运算符退栈并取出数据栈的所需元素个数进行相应的运算同时将运算结果压入数据栈中,直至运算符栈为空或者栈顶元素为+、-、*、/。
(5)、若将要压入的元素为(,则直接压入栈中。
(6)、若将要压入的元素为),则依次将运算符退栈并取出数据栈的所需元素个数进行相应的运算同时将运算结果压入数据栈中,直至栈顶元素为(,并将栈顶元素(退出。
注意:
为了处理负数数据的情况,采用的策略是,初始化数据栈的同时压入一个数据0。表达式处理结束后,数据栈的栈顶元素即为该Item项的值。

3、代码实现
由于代码量比较大,所以在这里就不再展示了。完整代码已上传至github,请有需要的自行上github浏览或下载。
链接:https://github.com/auroraZHONG/expression.git
正确打开路径:
viewcode------>Consoleapp3------->Program.cs

4、运行结果
C#实现复杂表达式的计算_第1张图片

你可能感兴趣的:(C#实现复杂表达式的计算)