终于调了半天bug完成一版,但是与win10自带的计算器有差值,明天在搞
# Author:AD
# Date:2020/2/27
'''
开发一个简单的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等类似功能偷懒实现),运算后得出结果,结果必须与真实的计算器所得出的结果一致
hint:
re.search(r'\([^()]+\)',s).group()
'(-40/5)'
'''
#!/usr/bin/env Python
# coding=utf-8
import re
# 利用re编译通用去字符的规则空格,括号
delet = re.compile('[' ', \( , \)]')
# 功能:加减运算,
# 输入:字符串(有可能带括号,空格,++,-+,+-、--都删除)
# 输出:数字(string)
# 测试案例:(--4.5 + 5.4)、4 +5、-+3-6、-3-4
def add_sub(str_input):
str_input = delet.sub('', str_input) #移除空格和括号
str_input = re.sub('(\+-)|(-\+)', '-', str_input) #将-+ +- 换为 -可行的方式之一
# str = re.sub('[+\-,\-+)]', '-', str) #不行的方式之一
str_input = re.sub('(\+\+)|(--)', '+', str_input) #将++ -- 换为+
str_num = re.split('[ \-, +]', str_input) # 将数放在一个列表中
if '' in str_num:
str_num.remove('') #开头有 - 的话会产生一个空元素,将其移除
str_sign = re.findall('[+, \-]', str_input) #存入符号
if len(str_sign) != len(str_num): #为了后面计算一致性,如果前面没有符号增加正号
str_sign.insert(0, '+')
i = 0 #统计数据列表元素用的次数
sum = 0 #统计最后的和
for s in str_sign:
if s == '+':
sum += float(str_num[i])
i += 1
else:
sum -= float(str_num[i])
i += 1
return str(sum)
'''
功能:实现乘除功能
输入:带括号的乘除表达式(可能含有空格、( 、)带正负号)
输出:计算完成的字符串
'''
def multi_divi(str_input):
str_input = delet.sub('', str_input) #移除空格和括号
num_negative = len(re.findall('-', str_input)) #将负号个数取出,为判断最终正负使用 防止有-4*(-5)的情况
str_input = str_input.replace('-', '') #去掉符号,为后面计算做准备
str_num = re.split('[*, /]', str_input) #按照乘除将其分开为数的列表
if '' in str_num:
str_num.remove('') # 开头有 的话会产生一个空元素,将其移除
str_sign = re.findall('[*, /]', str_input) # 存入符号
sum = 0.0 #记录结果
i = 1 #记录数列表用的次数,从1开始循环,符号肯定比数少一个
sum = float(str_num[0])
while i < len(str_num):
if str_sign[i-1] == '/':
sum /= float(str_num[i])
i += 1
else:
sum *= float(str_num[i])
i += 1
if num_negative % 2 == 0:
return str(sum)
else:
return str(-sum)
'''
功能:处理一个括号单元的内容
输入:不包含括号的最底层运算式子
输出:计算结果(str)
'''
def calculate_brackets(str_input):
str_input = delet.sub('', str_input)
str_input = re.sub('(\+-)|(-\+)', '-', str_input) # 将-+ +- 换为 -可行的方式之一
str_input = re.sub('(\+\+)|(--)', '+', str_input) # 将++ -- 换为+
ismulti_divi = ('*' in str_input) or ('/' in str_input)
isadd_sub = ('+' in str_input[1:]) or ('-' in str_input[1:])
if ismulti_divi and isadd_sub:
lst_multi_divi = re.split('[+, \-]', str_input)
if '' in lst_multi_divi: #移除空格
lst_multi_divi.remove('')
lst_multi_divi_sign = re.findall('[+, \-]', str_input) #拼接结果使用
if len(lst_multi_divi_sign) != len(lst_multi_divi): # 为了后面计算一致性,如果前面没有符号增加正号
lst_multi_divi_sign.insert(0, '+')
sum = '' # 记录最终结果
i = 0 #记录次数拼接符号
for mult in lst_multi_divi:
sum = ''.join([sum, lst_multi_divi_sign[i], multi_divi(mult)])
i += 1
return add_sub(sum)
elif ismulti_divi:
return multi_divi(str_input)
else:
return add_sub(str_input)
def main():
str_input = input('please input what to calculate:\n>>>')
#str_input = '1 - 2 * ((60 - 30 + (-40 / 5) * (9 - 2 * 5 / 3 + 7 / 3 * 99 / 4 * 2998 + 10 * 568 / 14)) - (-4 * 3) / (16 - 3 * 2))'
#'1-2*((60-30+(-40/5)*(9-2*5/3+7/3*99/4*2998+10*568/14))-(-4*3)/(16-3*2))'
str_input = re.sub(' ', '', str_input)
str_input = re.sub('(', '(', str_input)
str_input = re.sub(')', ')', str_input)
while '(' in str_input:
str_cal = re.findall('\([^(,)]*\)', str_input)
for i in str_cal:
str_input = str_input.replace(i, calculate_brackets(i))
return calculate_brackets(str_input)
if __name__ == '__main__':
print(main())