模块-作业题

# -*- encoding:utf-8 -*-

'''
01 re模块方法中的re.search()和re.findall的区别:
    (1)re.search():逐个寻找,寻找后就返回。
    (2)re.findall():全部找到后一起返回。
02 ret和res的区别
    (1)ret默认是return的缩写。
    (2)res默认是result的缩写。
'''
import re


def cal_min_exp(min_exp):
    '''
    01 计算最小表达式中的乘除法
    :param min_exp:
    :return:
    '''
    if "*" in min_exp:
        v1, v2 = min_exp.split("*")  # 将min_exp按照乘法进行分割,因为min_exp是字符串“2*5”,所以需要分割。
        return str(float(v1) * float(v2))  # 分割后强制转换为浮点型进行计算,最后要返回字符型,因为需要以字符型进行替换。
    elif '/' in min_exp:
        v1, v2 = min_exp.split("/")
        return str(float(v1) / float(v2))


def dealwith(son_exp):
    '''
     整理加加减减去重
    :param son_exp:
    :return:
    '''
    son_exp = son_exp.replace('__', '+')
    son_exp = son_exp.replace('+_', '-')
    son_exp = son_exp.replace('++', '+')
    son_exp = son_exp.replace('_+', '_')
    return son_exp


def calculate(son_exp):
    '''
    01 计算没有括号的表达式
    02 计算原则:先计算乘除,在计算加减
    :param son_exp:
    :return:
    '''
    son_exp = son_exp.strip("()")
    while 1:  # 用于完成表达式中的乘除法计算。
        '''
        匹配规则:\d+\.?\d*[*/]-?\d+\.?\d*
        '''
        ret = re.search("\d+\.?\d*[*/]-?\d+\.?\d*", son_exp)
  
        if ret:
            min_exp = ret.group()
            res = cal_min_exp(min_exp)  # 计算乘除法,并且将结果返回。
            son_exp = son_exp.replace(min_exp, res, 1)
        else:
            break
    son_exp = dealwith(son_exp)  # 整理加加减减去重,例如 3-+1--2之类。
    res = re.findall('[+-]?\d+\.?\d*', son_exp)
    sum = 0
    for i in res:
        sum = sum + float(i)
    return str(sum)

def remove_bracket(express):
    '''
    01 函数作用:把内部不再有小括号的表达式匹配出来,
    02 正则表达式:\([^()]+\)
    03 该处匹配的方法建议使用re.search,通过该方法进行一个个匹配,匹配后即返回,可以如果用re.findall全部取出会有一些不可预估
       的问题出现。
    '''
    while 1:
        ret = re.search('\([^()]+\)', express)  # 根据正则逐个匹配出满足内部不再有小括号的表达式出来。
        if ret:  # 判断返回的表达式是否为真。
            son_exp = ret.group()  # 将子表达式表示出来,ret是个对象,通过调用函数group即可将表达式表示出来。
            '''
            01 取值后进行计算。
            '''
            ret = calculate(son_exp)
            express = express.replace(son_exp, ret, 1)  # 需要指定替换次数,否则全部替换的话,会将2*5000中前面的2*5也直接替换为计算后的值
        else:
            break
    return express


def main(express):
    express = express.replace(' ', '')  # 首先去除表达式的空格。
    express = remove_bracket(express)  # 调用函数,去括号,把内部不再有小括号的表达式匹配出来。
    ret = calculate(express)
    print("计算结果:", ret)


if __name__ == '__main__':  # 用于调试,如果未被调用时__name__等于__main__可以执行,如果被调用,则__name__等于模块名,不能执行当前文件。
    print('输入计算的内容或输入Q退出'.center(30, '*'))  #
    while 1:
        # express = '-1 + 2 * ( (60-30 +(-40/5) * (9-2*5/3 + 7 /3*99/4*2998 +10 * 568/14 )) - (-4*3)/ (16-3*2) )'
        
        express = input('please enter: ')
        
        if express == 'Q' or express == 'q':
            break
        elif '/0' in express:
            print('0不能为被除数')
        elif express.count('(') != express.count(')') or '=' in express:  # 统计()的是否是成对出现,并且算式中是否出现"="
            print('表达式错误,请重新输入')
        else:
            main(express)

 

posted @ 2018-12-03 14:50  马玉刚  阅读(193)  评论(0)    收藏  举报