# 开发一个简单的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等类似功能偷懒实现),运算后得出结果,结果必须与真实的计算器所得出的结果一致

一.对公式进行简单处理(去掉空格及公式化简)
import re

def format_string(string):
    string = string.replace(' ','')
    string = string.replace('++','+')
    string = string.replace('+-','-')
    string = string.replace('-+','-')
    string = string.replace('--','+')
    string = string.replace('*+','*')
    string = string.replace('/+','/')
    return string

二.对于不符合要求的公式进行异常处理,给出错误提示信息

def check_expression(string):
    check_result = True
    if not string.count("(") == string.count(")"):
        print('括号不对称')
        check_result = False
    if re.findall('[a-z]',string.lower()):
        print('表达式有错,包含非法字符')
        check_result = False
    return check_result

三.进行乘除运算,并将计算的结果替换掉原公式中的乘除法运算

def mul_div(string):
  #正则表达式匹配(x乘以y或x除以y) regular = '\d+\.?\d*([*/]|\*\*)[\-]?\d+\.?\d*'
  #一直到公式中没有除法或乘法运算时,退出循环 while re.findall(regular,string): expression = re.search(regular,string).group()
  #计算乘法,并将计算的结果替换原来的式子
if expression.count("*") == 1: x,y = expression.split('*') mul_result = str(float(x) * float(y)) string = string.replace(expression,mul_result) string = format_string(string)
  #计算除法,并将计算的结果替换原来的式子
if expression.count("/") : x,y = expression.split('/') div_result = str(float(x) / float(y)) string = string.replace(expression,div_result) string = format_string(string) return string

四.进行加减法运算

def add_sub(string):
     sub_regu = '[\-]?\d+\.?\d*\-[\-]?\d+\.?\d*'
     add_regu = '[\-]?\d+\.?\d*\+[\-]?\d+\.?\d*'
     #计算加法
     while re.findall(add_regu,string):
         add_list = re.findall(add_regu,string)
         for add_str in add_list:
             x,y = add_str.split("+")
             add_result = "+" + str(float(x) + float(y))
             string = string.replace(add_str, add_result)
     #计算减法
     while re.findall(sub_regu,string):
        sub_list = re.findall(sub_regu,string)
        for sub_str in sub_list:
            numbers = sub_str.split('-')
            if len(numbers) == 3:
                result = 0
                #计算-1-2这种情况
                for v in numbers:
                    if v:
                        result -= float(v)
            else:
                x,y = numbers
                result = float(x)-float(y)
            string = string.replace(sub_str,"+" + str(result))
            string = format_string(string)
     return string

五.轮子造好了,主逻辑程序

if __name__ =="__main__":
if check_expression(source): strs = format_string(source) while source.count('(') > 0:
#匹配最里层括号的内容 strs
= re.search('\([^()]*\)',source).group() replace_str = mul_div(strs) replace_str = add_sub(replace_str)
       #每次计算的结果去掉括号 source
= format_string(source.replace(strs,replace_str[1:-1])) # print(source)
#else下边的逻辑是计算不带括号的式子 else: replace_str = mul_div(source) replace_str = add_sub(replace_str) source = source.replace(source,replace_str) print(source)

 

 

六.总结-难点

1.匹配最里层的式子:'\([^()]*\)'

2.匹配乘除法及加减法的正则表达式

3.主逻辑的设计

 

七.总程序

import re

def format_string(string):
    string = string.replace(' ','')
    string = string.replace('++','+')
    string = string.replace('+-','-')
    string = string.replace('-+','-')
    string = string.replace('--','+')
    string = string.replace('*+','*')
    string = string.replace('/+','/')
    return string

def mul_div(string):
    "计算乘除运算,所得的结果替换原先的表达式返回"
    regular = '\d+\.?\d*([*/]|\*\*)[\-]?\d+\.?\d*'
    while re.findall(regular,string):
        expression = re.search(regular,string).group()
        if expression.count("*") == 1:
            x,y = expression.split('*')
            mul_result = str(float(x) * float(y))
            string = string.replace(expression,mul_result)
            string = format_string(string)
        if expression.count("/") :
            x,y = expression.split('/')
            div_result = str(float(x) / float(y))
            string = string.replace(expression,div_result)
            string = format_string(string)
    return string

def add_sub(string):
     sub_regu = '[\-]?\d+\.?\d*\-[\-]?\d+\.?\d*'
     add_regu = '[\-]?\d+\.?\d*\+[\-]?\d+\.?\d*'
     #计算加法
     while re.findall(add_regu,string):
         add_list = re.findall(add_regu,string)
         for add_str in add_list:
             x,y = add_str.split("+")
             add_result = "+" + str(float(x) + float(y))
             string = string.replace(add_str, add_result)
     #计算减法
     while re.findall(sub_regu,string):
        sub_list = re.findall(sub_regu,string)
        for sub_str in sub_list:
            numbers = sub_str.split('-')
            if len(numbers) == 3:
                result = 0
                #计算-1-2这种情况
                for v in numbers:
                    if v:
                        result -= float(v)
            else:
                x,y = numbers
                result = float(x)-float(y)
            string = string.replace(sub_str,"+" + str(result))
            string = format_string(string)
     return string

def check_expression(string):
    check_result = True
    if not string.count("(") == string.count(")"):
        print('表达式有错,括号不对')
        check_result = False
    if re.findall('[a-z]',string.lower()):
        print('表达式有错,包含非法字符')
        check_result = False
    return check_result

if __name__ =="__main__":
    source = '1 - 2 * ( (60-30 +(-40/5) * (9-2*5/3 + 7 /3*99/4*2998 +10 * 568/14 )) - (-4*3)/ (16-3*2) )'
    if check_expression(source):
        strs = format_string(source)
        while source.count('(') > 0:
            strs = re.search('\([^()]*\)',source).group()
            replace_str = mul_div(strs)
            replace_str = add_sub(replace_str)
            source = format_string(source.replace(strs,replace_str[1:-1]))
        else:
            replace_str = mul_div(source)
            replace_str = add_sub(replace_str)
            source = source.replace(source,replace_str)
    print(source)

 

posted on 2017-08-20 23:46  西雅图的邂逅  阅读(260)  评论(0)    收藏  举报