老男孩Day6作业:计算器

Posted 空s蝉灬

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了老男孩Day6作业:计算器相关的知识,希望对你有一定的参考价值。

作业需求:

1、实现加减乘除及拓号优先级解析

2、用户输入
1 - 2 * ( (60-30 +(-40/5) * (9-2*5/3 + 7 /3*99/4*2998 +10 * 568/14 )) - (-4*3)/ (16-3*2) )
等类似公式后

3、必须自己解析里面的(),+,-,*,/符号和公式(不能调用eval等类似功能偷懒实现),

4、运算后得出结果,结果必须与真实的计算器所得出的结果一致

 

1)流程图

 

首先,根据计算符号的优先级考虑,带有括号的优先级最高,需要优先计算括号内的式子,计算完括号内的式子之后,破除括号,再进行加减乘除的运算。在四则运算中,加减运算是一个优先级的,乘除运算是一个优先级的,那么我们就可以先行计算乘除,将整个式子中的乘除全部计算完成以后,再次进行加减的计算,最终可以得到运算的结果

2、程序会判断用户输入的表达式是否符有效并给出相应提示

2、用户在主界面中输入:"q"程序会退出

3、程序通过eval函数计算出正确计算结果

 

二、具体实现

#-*- Coding:utf-8 -*-
# Author: D.Gray
import re,sys
\'\'\'
要求:
1\\实现加减乘除及拓号优先级解析
2\\用户输入
1 - 2 * ( (60-30 +(-40/5) * (9-2*5/3 + 7 /3*99/4*2998 +10 * 568/14 )) - (-4*3)/ (16-3*2) )
等类似公式后,必须自己解析里面的(),+,-,*,/符号和公式(不能调用eval等类似功能偷懒实现),
运算后得出结果,结果必须与真实的计算器所得出的结果一致
\'\'\'
def compute_mul_div(mg):
    \'\'\'
    定义一个乘除函数
    :param mg:
    :return:
    \'\'\'
    num = mg[0]  #  -40/5
    match = re.search("\\d+\\.*\\d*[\\*\\/]+[\\+\\-]?\\d+\\.*\\d*",num)
    if not match:
        return
    content = re.search(\'\\d+\\.*\\d*[\\*\\/]+[\\+\\-]?\\d+\\.*\\d*\',num).group()
    if len(content.split(\'*\')) > 1:
        v1,v2 = content.split(\'*\')
        value = float(v1) * float(v2)
        # print(\'v1>>>%s and v2>>>%s\'%(str(v1),str(v2)))
        # print(\'computer_mul:%s and %s\'% (str(content),str(value)))
    else:
        v1, v2 = content.split(\'/\')
        value = float(v1) / float(v2)
        # print(\'v1>>>%s and v2>>>%s\' % (str(v1), str(v2)))
        # print(\'computer_del:%s and %s\' % (str(content),str(value)))
    pur,suf = re.split(\'\\d+\\.*\\d*[\\*\\/]+[\\+\\-]?\\d+\\.*\\d*\',num,1)
    new_str = \'%s%s%s\'%(pur,value,suf)
    mg[0] = new_str
    #print(\'pur>>>%s    value>>>%s     uer>>>%s   new_str>>>%s\' % (pur, value,suf,new_str))
    compute_mul_div(mg)

def compute_add_sub(mg):
    \'\'\'
    运算表达式加减函数
    :param mg:
    :return:
    \'\'\'
    while True:
        if mg[0].__contains__(\'+-\') or mg[0].__contains__(\'++\') or mg[0].__contains__(\'-+\') or mg[0].__contains__(\'--\'):
            mg[0] = mg[0].replace(\'+-\', \'-\')  # 将-替换掉+-
            mg[0] = mg[0].replace(\'++\', \'+\')  # 将+替换掉++
            mg[0] = mg[0].replace(\'-+\', \'-\')  # 将-替换掉-+
            mg[0] = mg[0].replace(\'--\', \'+\')  # 将+替换掉--
        else:
            break
    if mg[0].startswith(\'-\'):  # 如果arg的第0个元素是以-开头
        mg[1] += 1  # arg的第一个元素自加1
        mg[0] = mg[0].replace(\'-\', \'&\')
        mg[0] = mg[0].replace(\'+\', \'-\')
        mg[0] = mg[0].replace(\'&\', \'+\')  # 将-变+,+变-
        mg[0] = mg[0][1:]  # 将arg中第0个元素中前面多出来的符号去掉
    num = mg[0]  # -40/5
    match = re.search(\'\\d+\\.*\\d*[\\+\\-]{1}\\d+\\.*\\d*\',num)
    if not match:
        return
    content = re.search(\'\\d+\\.*\\d*[\\+\\-]{1}\\d+\\.*\\d*\',num).group()
    if len(content.split(\'+\')) > 1:
        v1, v2 = content.split(\'+\')
        value = float(v1) + float(v2)
        # print(\'v1>>>%s and v2>>>%s\' % (str(v1), str(v2)))
        # print(\'computer_add:%s and %s\' % (str(content),str(value)))
    else:
        v1, v2 = content.split(\'-\')
        value = float(v1) - float(v2)
        # print(\'v1>>>%s and v2>>>%s\' % (str(v1), str(v2)))
        # print(\'computer_sub:%s and %s\' % (str(content),str(value)))
    pur,suf = re.split(\'\\d+\\.*\\d*[\\+\\-]{1}\\d+\\.*\\d*\',num,1)
    new_str = \'%s%s%s\'%(pur,value,suf)
    mg[0] = new_str
    compute_add_sub(mg)

def calate(match_group):
    \'\'\'
    计算表达式函数
    :param match_group:
    :return:
    \'\'\'
    mg = [match_group.strip(\'()\'),0]   # mg = [\'-40/5\']
    compute_mul_div(mg)     #调用乘除运算函数
    compute_add_sub(mg)     #调用加减运算函数
    if divmod(mg[1],2)[1] == 1:
        result = float(mg[0])
        result *= -1
        #print(\'divmod_result:%s\'%result)
    else:
        result = float(mg[0])
    #print(\'in the calator-new_str():%s\'%mg)
    return result

def kuohao(calculate):
    \'\'\'
    取出表达式中括号函数
    :param calculate:
    :return:
    \'\'\'
    while True:
        match = re.search(\'\\([^()]+\\)\',calculate)   #使用正则表达式 取出优先级最高的括号 并计算
        if match:   #如果表达式中有括号
            match_group = match.group() #
            match_result = calate(match_group)  #调用计算函数
            calculate = calculate.replace(match_group,str(match_result)) #将括号计算后的结果替换原参数
        else:   #若表达式中没有括号
            calate(calculate)
            break
    return calate(calculate)

print(\'\\033[33m 欢迎使用计算器 :\\033[0m\'.center(50,\'-\'))
print(\'例:1-2*((60-30+(-40/5)*(9-2*5/3+7/3*99/4*2998+10*568/14))-(-4*3)/(16-3*2))\')
while True:
    calculate_input = input(\'\\033[32m请输入计算的表达式 | (退出:q)>>>\\033[0m\')
    calculate_input = re.sub(\'\\s*\',\'\',calculate_input)
    if calculate_input == \'q\':
        exit(\'程序退出\')
    if len(calculate_input) == 0:
        continue
    if re.search(\'[^\\d\\+\\-\\*/\\(\\)]\',calculate_input):   #使用正则表达式判断用户输入是否是数字、"+-*/"、"()"
        print(\'\\033[31m 输入错误,请重新输入!!!\\033[0m\')
    else:
        result = kuohao(calculate_input)    #调用去除括号的函数
        print(\'\\033[34m 计算结果>>>%s\\033[0m\'%result)
        print(\'\\033[35m 正确结果>>>%s\\033[0m\' % eval(calculate_input))

 

以上是关于老男孩Day6作业:计算器的主要内容,如果未能解决你的问题,请参考以下文章

老男孩python DAY6 正则表达式

老男孩DAY1作业二

老男孩Day8作业:FTP

老男孩python第八次作业

老男孩作业day1—用户登陆

老男孩Python3.5培训第一周作业