紧接着上一节:
如果是“30+2*6-2”,那就出问题了,这是代码中哪里考虑的不周全呢
当运算式是 30+2*6-2 的时候,它这样扫描
现在把30当成 3和0入栈了,把30这一个数当成3和0这两个数来处里了,必然出问题了
现在处理多位数的运算
我们把这段代码:把数字入数字栈
改成:
这里有个新的变量$keepNum做字符串运算,需要在while循环前就得先定义好它。
看运算结果:
计算正确了。
现在还有需要改进的地方,还没有完美
当碰到运算式:7*2-5*3-3 //14-15-3=-4,又会出错了。
这不是我们想要的结果
分析为什么会出错呢?
过程:
(1)首先扫描到一个数字7,直接入数栈
(2)继续扫描发现是一个*,现在符号栈是空的,直接入符号栈
(3)继续扫描发现是一个数字2,直接入数栈
(4)继续扫描发现是一个-,现在符号栈不为空,并且-小于当前符号栈栈顶*的运算优先级,则计算。从数栈弹出两个数,从符号栈弹出一个运算符。即从数栈弹出7和2,然后从符号栈弹出*。7*2=14,再把14入数栈,并把-入符号栈
如下图所示:
(5)继续扫描发现是一个数字5,直接入数栈
(6)继续扫描发现是一个*,现在符号栈不为空,*是高于当前符号栈栈顶-的运算优先级,那直接入符号栈
(7)继续扫描发现是一个数字3,直接入数栈
(8)继续扫描发现是一个-,现在符号栈不为空,并且-小于当前符号栈栈顶*的运算优先级,则计算。从数栈弹出两个数,从符号栈弹出一个运算符。即从数栈弹出5和3,然后从符号栈弹出*。5*3=15,再把15入数栈,这个时候就出现问题了
如下图所示:
(9)如果这个时候,你不加控制,就直接把刚才(8)中扫描到的-入栈。
【如果符号栈不为空,就要判读。如果当前运算符的优先级小于等于符号栈顶的这个运算符的优先级,就计算,并把计算结果入数栈,然后把当前符号入栈】。
现在再把-入符号栈,而不是让14和15进行运算,就出问题了。
现在把-入符号栈,看出什么问题,看错误的思路会得出什么结果
(10)接着(9)中直接把-入符号栈的思路,继续扫描发现是一个数字3,直接入数栈
如下图所示:
至此扫描完毕
(11)现在开始依次弹出,先从数栈弹出3和15,从符号栈弹出-,计算15-3-->12(为什么是15-3,Stack类的方法getResult($num1,$num2,$oper),$res=$num2-$num1;即用后出栈的数减先出栈的数)。然后把结果12再入数栈
(12)再从数栈弹出12和14,从符号栈弹出-,计算14-12--->2,然后再把结果2入数栈,此时符号栈已经为空了,最终结果为2!!!★很显然这是不对的7*2-5*3-3 //14-15-3=-4,而不是2.
★问题出在哪里了呢?★是(8)中扫描到的-,-要入符号栈,就要先判断在符号栈中是否有和你-相等运算级别的运算符号,而不是直接就入符号栈省去判断的步骤。所以此时的-想入符号栈,就要不停的判断,只要它的优先级小于等于符号栈栈顶的优先级,则数栈和符号栈就一直向下运算,直到它的优先级大于符号栈栈顶的优先级,此时它才能入符号栈。
所以把思路修改如下:
【如果符号栈不为空,就要判读。如果当前运算符的优先级小于等于符号栈顶的这个运算符的优先级,就计算,并把计算结果入数栈,然后把当前符号入栈】。
改为:
【如果符号栈不为空,就要判读。如果当前运算符的优先级小于等于符号栈顶的这个运算符的优先级,就计算,并把计算结果入数栈,一直到当前符号的运算级别大于符号栈栈顶的优先级,才把当前符号入栈】
代码非常好改,就是把if语句改成while语句
改成:
看运算结果正确了
到此,这个计算器还缺少加上小括号的运算
6*8-(90-78)+60-45
更深一步:6*{8-[(90-78)+60]-45} 如此就相当的复杂了