计算器制作JAVA版(第三步,表达式求值(+-*/))

系统 1938 0

这个东西一直是大家关注的热点,也是这个题目的真正目标所在,希望大家能够好好学习了解这个部分的思路想法。虽然这个思路不是以后编译原理上面的标准思路,也不是什么正统方法,但是它确实符合大家的想法和一贯的思路。因为不够正统和强悍,如有高人敬请指点。
那么我们来考虑一下这个表达式,如果只有加减运算符大家是否感觉能很好的解决呢?
首先是单位的数字和运算符(只有加减),那么我们就只用顺序处理即可。形如:a+b-c+d,我们是如何计算的呢?首先计算a+b,然后将结果e替代a+b-->e-c+d-->h+d-->i一次一次计算替换的反复。如此以来我们就有了一个思路,拿出三个,计算结果丢进去,再拿出三个计算。我们假设,这个表达式已经切割好了,放在一个栈(第二步有讲)里面,我们通过对栈操作实现全部运算。

first : =  pop()
while     stack is not empty
    
do        operator : =  pop()
               second    :
=  pop()
               res            :
=   first    < operator >   second
               push(res)
               first          :
=   pop()
return  first

以上的计算是基于:运算符优先级一样,格式正确。剩下的就是来切割解析这个表达式使之成为这种结构。我们只需要一直解析这个字符串,如果出现,标点则前面的就是一个数,我们将它压入栈中。就是类似的方法喽。

p: = ""
n:
= 1
while    n <= length[expression]
        
do       if    expression[n] is the operator
                       then     
if    not   p = ""
                                          then   push(p)
                                                      p=""
                                    push(expression[n])
                       
else       p: = p + expression[n]
                 n:
= n + 1
return  stack


好了,我们现在是同优先级的没有问题了,如果有高优先级的怎么办呢?
如果只考虑+-*/那么只要是*/号出现就可以对其操作符左右的数据进行运算了。也就是说在上面的伪代码里面我们需要加一步判断operator是否为*/的情况,然后进行运算。但是如果我们只扫描到operator就要运算,对于一个双目运算符来说还差一边啊,那么我们能否将这个判断推迟到压入数字的时候进行呢?这样我们需要在压入数据的时候提出前面的若干项进行处理了。

p: = ""
n:
= 1
while    n <= length[expression]
        
do       if    expression[n] is the operator
                       then     
if    not   p = ""
                                          then   
                                                     
// Be careful
                                                     operator : =  pop()
                                                     
if     operator is the  *   or  /
                                                            then  
                                                                    first :
=  pop()
                                                                    second :
= p
                                                                    p:
=  first  < operator >  second
                                                     push(p)
                                                     p
= ""
                                    push(expression[n])
                       
else       p: = p + expression[n]
                 n:
= n + 1
return  stack

如此以来我们实现了+-*/了,HOHO 不错吧,思路就是这样一步一步来的。

下面我们想加入括号了,现在我们继续想,其实括号就是更高的一层优先级了,由于基于以上的运算处理,在括号“缝合”(即碰到了')')的时候括号里面只有加减法,也就是说刚刚的栈处理结束标志是表达式末尾开始的标志就是表达式开头,而这里的开头是‘(’结尾是‘)’,还有什么区别吗?其实没什么了,那么我们按照这个思路,如果expression[n]是括号,‘(’压入栈中,')'开始运算将结果压入栈中。这样看似乎不难哦。

p: = ""
n:
= 1
while    n <= length[expression]
        
do       if    expression[n] is the operator
                       then     
if    not   p = ""
                                          then   
                                                     
// Be careful
                                                     operator : =  pop()
                                                     
if     operator is the  *   or  /
                                                            then  
                                                                    first :
=  pop()
                                                                    second :
= p
                                                                    p:
=  first  < operator >  second
                                                     push(p)
                                                     p
= ""
                                    push(expression[n])
                       elseif   expression[n] is the bracket ( or )
                                   then
                                           
if   expression[n] = " ( "
                                               then push(expression[n])
                                               
else   res:=compute the expression between the  " ( "  and  " ) "
                                                         //Push the result
                                                         push(res)
    
                       
else       p: = p + expression[n]
                 n:
= n + 1
return  stack

这样看似乎很爽啊,但是大家看看这个表达式  1+(2+3*4)*(5+6)
计算结果是 165  而不是正确结果 155.为什么呢?
因为我们在计算之后直接压入栈中而忽略了前面的那个*号。至此我们应该知道,一旦压入数据就得检查前面的operator.
这样以来我们需要对push(object)单独再包装一下,使它明白只要压入就得检查.

至此我们已经知道了基本的运算体系。
在实际编码过程中,大家可能要碰到大量的边界讨论问题,这一定要小心。
关于乘方和小数问题我将尽快写出来。

计算器制作JAVA版(第三步,表达式求值(+-*/))


更多文章、技术交流、商务合作、联系博主

微信扫码或搜索:z360901061

微信扫一扫加我为好友

QQ号联系: 360901061

您的支持是博主写作最大的动力,如果您喜欢我的文章,感觉我的文章对您有帮助,请用微信扫描下面二维码支持博主2元、5元、10元、20元等您想捐的金额吧,狠狠点击下面给点支持吧,站长非常感激您!手机微信长按不能支付解决办法:请将微信支付二维码保存到相册,切换到微信,然后点击微信右上角扫一扫功能,选择支付二维码完成支付。

【本文对您有帮助就好】

您的支持是博主写作最大的动力,如果您喜欢我的文章,感觉我的文章对您有帮助,请用微信扫描上面二维码支持博主2元、5元、10元、自定义金额等您想捐的金额吧,站长会非常 感谢您的哦!!!

发表我的评论
最新评论 总共0条评论