通过正则表达式对四则运算表达式进行校验

时间:2024-10-04 07:41:53

最近在自考过程中碰到实现一个四则运算(加减乘除)的题目,该题解法有简单有复杂,简单的诸如只是单次输入数字或者加减乘除符号来检验判断运算表达式的有效性并给出结果,复杂的则在此基础上添加支持小数、算符优先级、括号等等逻辑。基于实用性的考虑,我选择了一次性输入整个四则预算表达式并给出计算结果的方向。由此面临最大的问题就是如何对四则运算表达式进行有效的校验,再三权衡后,选择通过正则表达式对输入进行有效性校验,先将思考过程分析如下:

1.对基础的非负整数之间的加减乘除进行校验,可以明确获得表达式规则为:表达式以数字开头,数字之后紧跟运算符,最终表达式以数字结尾,换言之就是“数字+运算符”多次出现,并以数字结尾。

推导可得正则表达式:^((\d)+[\-/\+\*])+(\d)+$ 注:该表达式不考虑单个数字场景,不支持负数

测试样例:6*3-2/1+5

2.在上一步基础上考虑对于小数的支持,将\d+替换成\d+(\.\d+)?

推导可得正则表达式:^(\d+(\.\d+)?[\-/\+\*])+(\d+(\.\d+)?)$

测试样例:6*3-2/0.1+0.45

3.考虑表达式存在负数,考虑括号场景,分析表达式规则添加规则:

(1)表达式中除非是表达式第一个字符或者在左括号右边,否则不能出现前置负号(-)来表达负数,其他场景必须通过左右括号包裹负数,正确表达式如:-3-1、(-3+2)/3、3+(-1),不能出现诸如:3--1、3+-2、3/-3

注:此处区分前置负号(仅用于表达负数)和运算符号(用于运算)

(2)数字(包含负数)左边可以出现零个或多个左括号,数字右边可以出现零个或多个右括号。

该正则表达式在最开始添加“-?”用于判断表达式是否是前置负号起始,如:-3+2、-3*(2+1)

在数字(\d+(\.\d+)?)之前添加“(\(-?)*”用于判断数字前面的零或多重左括号,每个左括号之后都可跟一个前置负号,如:(-(-(-3+2)-1)*2)

在数字(\d+(\.\d+)?)之后添加“\)*”用于判断数字后面的零或多重右括号

推导可得正则表达式:^-?((?)\d+(\.\d+)?*[\-/\+\*])+((?)\d+(\.\d+)?*)$

测试样例:((-3)+2*3-(6+3)/2)-6、(3+2*3.2-(6+3.5)/2)-6、(-(3-7)*2+3)/1、-(3*6-8)

4.考虑到表达式仅为一个数字、括号、前置负号的场景,添加逻辑判断“^-?(?)\d+(\.\d+)?*$”

推导可得正则表达式:^-?(?)\d+(\.\d+)?*$|^-?((?)\d+(\.\d+)?*[\-/\+\*])+((?)\d+(\.\d+)?*)$

测试样例:-231、(-231)、-(-231)、-23.123、(-231.1)

通过上述4步推导可以获得一个校验包含负数、小数、括号的正则表达式,但是该正则表达式无法校验表达式中左右括号出现的次序和数量是否准确,故而这部分逻辑需要额外的校验逻辑进行补足。

至于表达式的结果计算则需要将输入的表达式转换成逆波兰式,这部分算法不在此赘述。