PHP后缀表达式的实现

背景

  在电商的一个场景中,商品的价格计算表达式是配置出来的。
  那么价格计算表达式如何执行呢?在PHP里面,可以调用eval()函数,将代码作为参数来得到结果。
  但是,有个问题。如果表达式配置错误,eval函数无法捕捉任何的异常,会直接导致进程退出。另一方面,eval直接执行代码,存在代码注入的风险。
  在这样的场景下,我们就需要重新造轮子了。
  中缀表达式是我们平时习惯的写法,例如:1+(2*3-1)+34*3。下面以中缀表达式的方式进行拆解。

第一种情况,只有一种操作符

  我们考虑最简单的情况(只有一种操作符),[操作数][操作符][操作数],这也是最小的单元。比如:1+2。
  对于这种情况,我们只需要从字符串中取操作数,然后将表达式中的操作符映射到程序中的操作符即可。
  对于有多个操作符的,也可以将当前操作符以外的其余表达式折叠成一个操作数。
1+2+3+4,拆解为A=1+2;B=A+3;C=B+4。这样就通过递归(广义数组)的方式表达了这个模式。

第二种情况,考虑其他操作符。

  此时就出现了操作符的优先级的考虑了。
  操作符有+、-、*、/、%,操作数主要是浮点数和整数。
*、/、%为最高优先级,+、-为次级优先级。
  同种优先级的操作符,并无差异,回归到第一种情况的处理。当出现不同优先级时,高优先级操作符优先处理,然后再处理低优先级的操作符。
  优先级的高低是通过比较得来的。当相邻的两个操作符的优先级不相同时,我们就需要进行处理了(相同优先级直接计算)。
  为了知道相邻的操作符的优先级跟当前的操作符优先级是否相同,必须先去试探,获取下一个操作符,然后再决定当前操作符作何处理。
那么当前的操作符如何处理是依赖于下一个操作符的。

第三种情况,括号

  括号,屏蔽了操作符之间的优先级。拆分出了多个子表达式。拆分出来的每一个子表达式又回到第二种情况的处理方案。


  中缀表达式的实现,易于书写和阅读。但是实现起来并不方便。
  这里通过将中缀表达式转换为后缀表达式,然后再计算后缀表达式的值进行求解。
  中缀表达式转后缀表达式的过程,实际上就是第三种情况,括号一节的预处理。这个过程拆解了括号,后续我们只需直接执行四则运算。

具体实现请参考:https://github.com/panxl6/blog/blob/master/PHP-data-structure/Calculator.php

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值