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

本文介绍了一种使用栈处理算术表达式的算法,包括加减乘除及括号处理。通过逐步解析表达式并利用栈进行运算,实现了不同优先级运算符的计算。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

这个东西一直是大家关注的热点,也是这个题目的真正目标所在,希望大家能够好好学习了解这个部分的思路想法。虽然这个思路不是以后编译原理上面的标准思路,也不是什么正统方法,但是它确实符合大家的想法和一贯的思路。因为不够正统和强悍,如有高人敬请指点。
那么我们来考虑一下这个表达式,如果只有加减运算符大家是否感觉能很好的解决呢?
首先是单位的数字和运算符(只有加减),那么我们就只用顺序处理即可。形如: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)单独再包装一下,使它明白只要压入就得检查.

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值