开发要求:
开发一个简单的python计算器:
实现加减乘除及优先级解析;
用户输入类似这样的表达式: 1 - 2*((60-30 +(-40/5)*(9-2*5/3+7/3*99/4*2998 + 10*568/14))-(-4*3)/(16-3*2))
等类似公式后,必须自己解析里面的(),+,-,*,/符号和公式(不能调用eval等类似的功能实现,运算后得出结果)
计算结果必须与真实的计算器得出结果一致;
1. 功能分析:
用户输入一个类似这样 3*( 4+ 50 )-(( 100 + 40 )*5/2- 3*2* 2/4+9)*((( 3 + 4)-4)-4) 这样的表达式,
假设表达式里面除了包含空格、'+'、'-'、'*'、'/'和括号再无其他特殊符号,
然后自己动手写代码解析其中的表达式,实现加减乘除,
最后得出的结果与真实的计算机所算的结果必须一致。
2. 所需要的知识点:
1> 字符串的处理;
2> 正则表达式的运用;
3> 函数递归;
用户输入一个类似这样 3*( 4+ 50 )-(( 100 + 40 )*5/2- 3*2* 2/4+9)*((( 3 + 4)-4)-4) 这样的表达式,
假设表达式里面除了包含空格、'+'、'-'、'*'、'/'和括号再无其他特殊符号,
然后自己动手写代码解析其中的表达式,实现加减乘除,
最后得出的结果与真实的计算机所算的结果必须一致。
2. 所需要的知识点:
1> 字符串的处理;
2> 正则表达式的运用;
3> 函数递归;
3. 程序实现流程分析:
1> 用正则表达式处理字符串,只提取其中的数字和运算符,并转换成列表
2> 编写一个函数,处理没有括号的基本运算的基本表达式
3> 再写一个函数递归处理带有括号的函数,先计算最内部括号中的表达式, 然后将最内部的括号替换为计算后的结果, 在递归外部一层的, 最后返回的就是所需的结果
4. 具体实现过程:
1> 用正则表达式处理字符串,只提取其中的数字和运算符,并转换成列表
2> 编写一个函数,处理没有括号的基本运算的基本表达式
3> 再写一个函数递归处理带有括号的函数,先计算最内部括号中的表达式, 然后将最内部的括号替换为计算后的结果, 在递归外部一层的, 最后返回的就是所需的结果
4. 具体实现过程:
import re, sys
def input_str():
"""
输入表达式
return: 返回有限的表达式
"""
welcome_str = "超级计算器"
print(welcome_str.center(50,'*'),'\n') # 输出欢迎界面
while True:
iput = input("请输入你要计算的表达式[q:退出]:").strip()
if iput == 'q': # 退出计算
sys.exit("bye-bye")
elif len(iput) == 0:
continue
else:
iput = re.sub('\s*', '', iput) # 去除空格
return iput
"""
输入表达式
return: 返回有限的表达式
"""
welcome_str = "超级计算器"
print(welcome_str.center(50,'*'),'\n') # 输出欢迎界面
while True:
iput = input("请输入你要计算的表达式[q:退出]:").strip()
if iput == 'q': # 退出计算
sys.exit("bye-bye")
elif len(iput) == 0:
continue
else:
iput = re.sub('\s*', '', iput) # 去除空格
return iput
def chengchu(expression):
"""
乘除运算
:param expression: 表达式
:return: 返回没有乘除的表达式/最终的计算结果
"""
val = re.search("\d+\.?\d*[\*\/]+[\+\-]?\d+\.?\d*", expression) #匹配乘除号,能识别小数点和正负数,类似:['121.121*-121.12', '121/12.223', '3.4*4.5'];
"""
乘除运算
:param expression: 表达式
:return: 返回没有乘除的表达式/最终的计算结果
"""
val = re.search("\d+\.?\d*[\*\/]+[\+\-]?\d+\.?\d*", expression) #匹配乘除号,能识别小数点和正负数,类似:['121.121*-121.12', '121/12.223', '3.4*4.5'];
if not val: #如果不存在乘除,就直接返回表达式;
return expression
else:
data = re.search("\d+\.?\d*[\*\/]+[\+\-]?\d+\.?\d*", expression).group()
if len(data.split("*")) > 1: #以乘号分割
part1, part2 = data.split("*")
value = float(part1) * float(part2)
else:
part1, part2 = data.split("/")
if float(part2) == 0: #除数为0则为无效,退出
sys.exit("除数为0,计算表达式失败!!!")
value = float(part1) / float(part2)
return expression
else:
data = re.search("\d+\.?\d*[\*\/]+[\+\-]?\d+\.?\d*", expression).group()
if len(data.split("*")) > 1: #以乘号分割
part1, part2 = data.split("*")
value = float(part1) * float(part2)
else:
part1, part2 = data.split("/")
if float(part2) == 0: #除数为0则为无效,退出
sys.exit("除数为0,计算表达式失败!!!")
value = float(part1) / float(part2)
s1, s2 = re.split("\d+\.?\d*[\*\/]+[\+\-]?\d+\.?\d*", expression, 1)
next_expression = "%s%s%s" % (s1, value, s2)
return chengchu(next_expression)
next_expression = "%s%s%s" % (s1, value, s2)
return chengchu(next_expression)
def jiajian(expression):
"""
加减运算
:param expression: 表达式
:return: 返回没有计算的加减表达式/最终的计算结果
"""
expression = expression.replace("+-", "-") # 替换表达式
expression = expression.replace("--", "+") # 替换表达式
expression = expression.replace("++", "+") # 替换表达式
expression = expression.replace("-+", "-") # 替换表达式
"""
加减运算
:param expression: 表达式
:return: 返回没有计算的加减表达式/最终的计算结果
"""
expression = expression.replace("+-", "-") # 替换表达式
expression = expression.replace("--", "+") # 替换表达式
expression = expression.replace("++", "+") # 替换表达式
expression = expression.replace("-+", "-") # 替换表达式
val = re.search("\-?\d+\.?\d*[\+\-]{1}\d+\.?\d*", expression) # 匹配加减
if not val: # 如果不存在乘除,就直接返回表达式;
return expression
else:
data = re.search("\-?\d+\.?\d*[\+\-]{1}\d+\.?\d*", expression).group()
if len(data.split("+")) > 1: #以乘号分割
part1, part2 = data.split("+")
value = float(part1) + float(part2)
elif data.startswith("-"): #判断是否为负数开头
part0, part1, part2 = data.split("-")
value = -float(part1) - float(part2)
else:
part1, part2 = data.split("-")
value = float(part1) - float(part2)
s1, s2 = re.split("\-?\d+\.?\d*[\+\-]{1}\d+\.?\d*", expression, 1)
next_expression = "%s%s%s" % (s1, value, s2)
return jiajian(next_expression)
return expression
else:
data = re.search("\-?\d+\.?\d*[\+\-]{1}\d+\.?\d*", expression).group()
if len(data.split("+")) > 1: #以乘号分割
part1, part2 = data.split("+")
value = float(part1) + float(part2)
elif data.startswith("-"): #判断是否为负数开头
part0, part1, part2 = data.split("-")
value = -float(part1) - float(part2)
else:
part1, part2 = data.split("-")
value = float(part1) - float(part2)
s1, s2 = re.split("\-?\d+\.?\d*[\+\-]{1}\d+\.?\d*", expression, 1)
next_expression = "%s%s%s" % (s1, value, s2)
return jiajian(next_expression)
def remove_bracket(expression):
"""
Function: 去小括号运算
:param expression: 表达式
:return: 结果
"""
# 取最小括号内容:
# 安组匹配,将括号内容按组匹配,过滤内容不存在括号即为最内层括号
if not re.search(r"\(([^()])+\)", expression): #判断小括号,如果不存在直接计算。
ret1 = chengchu(expression)
ret2 = jiajian(ret1)
return ret2
else:
data = re.search(r"\(([^()]+)\)", expression).group() #取优先级最高的括号
# '( 4+ 50 )'
data = data.strip("[\(\)]") #去掉括号,格式:strip([chars])
# ' 4+ 50 '
# 遵守先乘除后加减
ret1 = chengchu(data)
ret2 = jiajian(ret1)
part1, replace_str, part2 = re.split(r"\(([^()]+)\)", expression, 1)
expression1 = "%s%s%s" % (part1, ret2, part2) # 将小括号的计算结果替换成表达式;
return remove_bracket(expression1)
if __name__ == "__main__":
try:
expression = input_str()
# expression = "3*( 4+ 50 )-(( 100 + 40 )*5/2- 3*2* 2/4+9)*((( 3 + 4)-4)-4)"
result = eval(expression) #用eval计算验证值;
expression = expression.replace(" ", "") #除了表达式中空格;
ret = remove_bracket(expression) #用函数计算式得出的记过;
result = float(result)
ret = float(ret)
if result == ret: #比较2种方式的计算结果,正确则输出结果
print("eval计算结果: %s" % result)
print("表达式计算结果: %s" % ret)
else: #不正确则提示异常,并返回结果
print("计算结果异常,请重新检查!")
print("eval计算结果: %s" % result)
print("表达式计算结果: %s" % ret)
except(SystemError, NameError, SyntaxError, ValueError, TypeError):
print("输入表达式不合法,请重新检查")
来源:oschina
链接:https://my.oschina.net/u/4274876/blog/3926847