引言
最近做一个配置的功能,需求是该配置项跟另一个整形配置项关联,具有一定的函数关系,例如有一个配置项是值为 N
,则另一配置 F
项满足函数关系F=2/(N+1)F=2/(N+1)。这个函数关系是客户手动输入,只需要简单的四则运算,所以我们要做的就是判断四则运算表达式是否有效,且给定 N
的值,算出表达式的值。
如何快速判断一个四则运算公式字符串是否符合规则,且根据给定值计算出该公式的值?
双栈实现
实际上编译器就是利用了双栈实现了的表达式求值,其中一个栈用来保存操作数,另一个栈用来保存运算符。
从左向右遍历表达式,当遇到数字时,就将其直接压入操作数栈;当遇到运算符时,就将其与运算符栈的栈顶元素比较。
如果遇到的运算符比运算符栈顶的元素的优先级高,就将这个运算符压入栈;
如果遇到的运算符比运算符栈顶的元素的优先级低或两者相同,就从运算符栈顶取出运算符,在从操作数栈顶取两个操作数,然后进行计算,并把计算的得到的结果压入操作数栈,继续比较这个运算符与运算符栈顶的元素;
下图表示一个简单四则运算表达式 3+5*8-6
的计算过程:
代码实现可以大概简化可以分为以下步骤:
-
定义运算符栈
operatorStack
和操作数栈operandStack
。 -
从左至右扫描表达式,遇到操作数时,直接将其推入操作数栈
operandStack
。 -
遇到运算符时,比较其与运算符栈顶部运算符的优先级:
-
如果该运算符的优先级高于或等于运算符栈顶部运算符,则将该运算符直接入栈
operatorStack
。 -
如果该运算符的优先级低于运算符栈顶部运算符,则将运算符栈顶部的运算符出栈,从操作数栈中弹出两个操作数,计算结果后再入栈
operandStack
,重复此步骤直到运算符栈为空或遇到优先级高于或等于该运算符的栈顶运算符为止。
-
-
遇到括号时:
-
如果是左括号“(”,则直接入栈
operatorStack
。 -
如果
-