在这种设计中,优先级被划分为7个级别:P0,P1,P2,P3,P4,P5,P6,P7,P0优先级最低,P7最高。
| 优先级 | 运算符 |
| P0 | # ( |
| P1 | + - |
| P2 | * / % |
| P3 | 保留 |
| P4 | sin,cos,tg,ctg,asin,acos,atg,actg |
| P5 | lg,log,ln |
| P6 | pow |
| P7 | 保留 |
我们规定:
1. 如果运算符栈顶的运算符优先级高于或等于当前读入的运算符优先级,则弹出栈顶运算符,同时从数栈弹出相应数量的操作数进行运算,将运算结果压入数栈,最后把当前运算符压入运算符栈。
2. 如果运算符栈顶的运算符优先级低于当前读入的运算符的优先级,则直接压入当前运算符到运算符栈。
3. 如果当前运算符为' ) ',则弹出运算符栈中的运算符进行相应的运算,直到弹出的运算符是' ( ' 为止。
4. 如果当前运算符为' ( ',则直接把' ( '压入运算符栈
要注意:这种算法在完成了 分词结果 的扫描之后,大多数情况下会在运算符栈和数符栈中留下未运算的运算符和数符,因此要依次弹出运算符和数符进行运算,直到栈顶出现#为止,因此在表达式中最后不使用#结尾,否则可能导致提前结束运算。
下面我们来看看用该优先级表进行运算的例子
表达式:1*2+(9-4)/5
| 步骤 | 数栈 | 运算符栈 | 当前输入符号 | 剩余表达式 | 说明 |
| 1 | 空 | # | 1*2+(9-4)/5 | ||
| 2 | 空 | # | 1 | *2+(9-4)/5 | |
| 3 | 1 | # | * | 2+(9-4)/5 | #优先级P0,*优先级P2,#的优先级<*的优先级,push(*) |
| 4 | 1 | # * | 2 | +(9-4)/5 | |
| 5 | 1 2 | # * | + | (9-4)/5 | +优先级P1,*优先级P2,*的优先级>+的优先级,pop(*),pop(1),pop(2),计算1*2=2,把结果2压入数栈 |
| 6 | 2 | # + | ( | 9-4)/5 | |
| 7 | 2 | # + ( | 9 | -4)/5 | |
| 8 | 2 9 | # + ( | - | 4)/5 | -的优先级> ( 的优先级,push(-) |
| 9 | 2 9 | # + ( - | 4 | )/5 | |
| 10 | 2 9 4 | # + ( - | ) | /5 | 遵循规则3,见上面的“我们规定……” |
| 11 | 2 5 | # + | / | 5 | + 优先级 < / 优先级 |
| 12 | 2 5 | # + / | 5 | 空 | |
| 13 | 2 1 | # + | 无 | 空 | 因为栈顶不为#,所以计算5/5=1,push(1) |
| 14 | 3 | # | 无 | 空 | 因为栈顶不为#,所以计算1+2=3,push(3) |
| 15 | 3 | # | 无 | 空 | 栈顶为#,完成 |
该优先级表可能存在一定的局限性,大家有兴趣的话可以探讨一下。
*********************** Update on 2005.5.14 *************************
为了说明该种优先级表的局限性,我们来看一个例子。
我们的表达式可能需要处理这样的情况:#cos sin 1#
该表达式中我们应该先计算sin1,再计算cos(sin 1),但根据该表的运算规则,我们会得到如下的运算步骤
| 步骤 | 数符栈 | 运算符栈 | 当前符号 | 剩余表达式 | 说明 |
| 1 | 空 | # | cos sin1 | ||
| 2 | 空 | # | cos | sin 1 | |
| 3 | 空 | # cos | sin | 1 | sin的优先级=cos的优先级,对cos进行运算 |
| 4 | 空 | # | sin | 出错,因为数符栈为空,cos缺少可以弹出的数符 |
本文探讨了一种优先级表的设计思路,将运算符优先级分为7个级别,并通过实例展示了如何利用该表进行数学表达式的计算。同时,指出了这种方法在处理某些特定运算符组合时存在的局限性。
2447

被折叠的 条评论
为什么被折叠?



