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

    流程图:

    readme:

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

    针对于本程序,需要注意的有以下几点:

    1、 可进行复杂运算处理,如

    a)      1-2*((60-30+(-40/5)*(9-2*5/3+7/3*99/4*2998+10*568/14))-(-4*3)/(16-3*2))

    效果如下图所示:

    其中该运算最终值是通过函数进行计算得到的值

    正确答案的值为通过eval()直接计算得到的值

    2、 若需要退出系统,则可以直接输入q退出。

     

    3、请保证值是在输入法为英文状态下输入的,若运算式中存在中文字符,则会出现计算失败的情况。如下图所示:

     

    最后两个字符为中文状态下输入的,不管是运算最终值还是正确答案,都无法进行此类数值的计算。

    4、 已知问题

    系统暂不支持计算指数函数,若进行计算,则最终返回值和正确答案的值都不正确。

    如下图所示:

     PS.初入python,难免会有遗漏之处,若有不妥之处,望多指教。

    代码:

    # -*- coding:utf-8 -*-
    
    import re
    
    
    #此处是用来计算乘法和除法的
    #乘法和除法优先级相同,先计算谁都可以,因此不会强制先计算谁
    def chengchu(chengchu_filter2):
        error_tag=""
        # if "/" in chengchu_filter2 or "*" in chengchu_filter2:
        #首先从传入值中提取第一组带有乘法或者除法的小组式子
        try:
            rep = re.search('\d+\.*\d*[\*\/]+[\+\-]?\d+\.*\d*', chengchu_filter2).group()
        #\d+\.*\d*[\*\/]+[\+\-]?\d+\.*\d*
        #\d+代表了匹配数字0-9 +号是表示连续数字按照一个来进行处理,代表了一个或者是多个的情况
        #\.*代表了小数点,代表了可以出现0次或者多次
        #\d*代表了小数点以后的数字可以出现0次或者多次
        #[\*\/]代表了 乘号* 除号/出现一个即可
        #[\+\-]?代表了+号 -号 出现一个即可,这里的+ - 代表的是正负
        #\d+\.*\d*代表了后面又有一个带小数的数值
        except:
            error_tag="无法计算"
            return error_tag
        if "/" in rep:#如果存在/,则开始进行除法运算
            n1,n2=rep.split("/")
            chengchu_filter3=float(n1)/float(n2)
        elif "*" in rep:#如果存在*,则开始乘法运算
            n1,n2=rep.split("*")
            chengchu_filter3=float(n1)*float(n2)
        #计算完成以后,将此小组式子带回原有的大式子中,然后将此值返回。
        chengchu_filter4=chengchu_filter2.replace(rep,str(chengchu_filter3))
        return chengchu_filter4
    
    def jiajian(chengchu_filter4):
        #此处的tag是用来证明传入的值仅剩下一个数了,无法再次进行运算。
        #此种情况最多的是为了应对带有负号的数值
        jiajian_tag=False
        #式子在经过简化或者运算,可能会出现以下几种情况,为了更好的计算,在此将这几种情况进行了合并。
        if "++" in chengchu_filter4:
            chengchu_filter_new=chengchu_filter4.replace("++","+")
        elif "+-" in chengchu_filter4:
            chengchu_filter_new=chengchu_filter4.replace("+-","-")
        elif "-+" in chengchu_filter4:
            chengchu_filter_new=chengchu_filter4.replace("-+","-")
        elif "--" in chengchu_filter4:
            chengchu_filter_new=chengchu_filter4.replace("--","+")
        else:#如果式子中没有分析出来对应的符号,那么就直接将原值带入下一步的计算中
            chengchu_filter_new=chengchu_filter4
        if "+" in chengchu_filter_new or "-" in chengchu_filter_new:
            try:
                #此处存在两个try except组,首先说最里面的一组,这一组是为了处理一种情况,就是-3+2这种,如果不进行此类情况的特殊处理,那么
                #就会造成这样的情况,系统首先进行3+2的计算,然后再进行- 的计算,这样就造成了这个式子的结果为-5,在此处需要顾及数字前面的符号
                #那么使用\A\W来进行单独抓取负数的负号,就可以避免出现这个问题。
                #\A是说从字符串的开头进行匹配, \W是说不匹配0-9a-zA-Z等数字,这样的话就只能匹配到+-*/等符号。数字前面也一般都是-号。
                #外面的这一组,是为了处理来的数完全不需要进行正则匹配处理,一旦进行匹配,就会出现问题,那这时候就说明了这个数已经成了—3这样情况的了
                #那么为了下一步的计算,直接在函数末尾进行赋值处理,同时将代表仅剩一个数的tag点亮,完成运算。
                try:
                    rep2=re.search('\A\W',chengchu_filter_new).group()+re.search('\d+\.*\d*[\+\-]{1}\d+\.*\d*',chengchu_filter_new).group()
                except:
                    rep2=re.search('\d+\.*\d*[\+\-]{1}\d+\.*\d*',chengchu_filter_new).group()
                if "+" in rep2:
                    n3,n4=rep2.split("+")
                    jiajian5=float(n3)+float(n4)
                elif "-"in rep2:
                    try:
                        n3,n4=rep2.split("-")
                        jiajian5=float(n3)-float(n4)
                    except:
                        jiajian6=chengchu_filter_new
                        jiajian_tag=True
                        return jiajian6,jiajian_tag
                #将计算好的式子替换到原有式子的相同位置,完成本次的运算。
                jiajian6=chengchu_filter_new.replace(rep2,str(jiajian5))
            except:
                jiajian6=chengchu_filter_new
                jiajian_tag=True
        else:#这种情况就是代表了进来的数值直接不需要进行计算。
            jiajian6=chengchu_filter_new
            jiajian_tag=True
        return jiajian6,jiajian_tag
    
    
    
    
    def jisuan(cal):
        cal2=cal
            #'\(([^()]+)\)'
            #这个式子仅需解释[^()]这部分即可。^()代表了除了()以外的其他数值,也就是说里面不可以出现括号,其他数值都可以,连起来的
            #其他数值也可以加在里面。
        cal_filter=re.findall(r'\(([^()]+)\)',cal)#此处是将所有的括号式子都已取出,因此下方需要使用循环来进行处理。
        if len(cal_filter)!=0:
            for i in range(0,len(cal_filter)):
                if "/" in cal_filter[i] or "*" in cal_filter[i]:#存在* /进行乘除运算
                    cal_filter3=chengchu(cal_filter[i])
                    if cal_filter3=="无法计算":#若式子进入乘除运算以后出现错误,会返回'无法计算'的值,直接将此值赋予给最终的值
                        return cal2
                    cal2=cal2.replace(cal_filter[i],cal_filter3)#计算完成以后,将计算过的数字赋回原值的相同位置
                else:#否则进行+-运算
                    cal_filter3,jiajian_tag=jiajian(cal_filter[i])
                    if jiajian_tag==True:
                        cal_filter[i]="("+cal_filter[i]+")"
                    cal2=cal2.replace(cal_filter[i],cal_filter3)
        elif len(cal_filter)==0:#此种情况是式子无法再进行分割,比如其中一种情况是式子中没有括号了。
            if "/" in cal2 or "*" in cal2:
                cal_filter3=chengchu(cal2)
                cal2=cal2.replace(cal2,cal_filter3)
            else:
                cal_filter3,jiajian_tag=jiajian(cal2)
                if jiajian_tag==True:
                    cal2="("+cal2+")"
                cal2=cal2.replace(cal2,cal_filter3)
                if "+" not in cal2 or "-" not in cal2 or "*" not in cal2 or "/" not in cal2:#此种情况是最终值了,形式为 2017
                    if "(" in cal2 or ")" in cal2:#这种情况则是(2017)
                        cal2=cal2.strip("()")
                    return cal2
        return jisuan(cal2)
    
    
    print("欢迎进入计算器".center(50,"-"))
    while True:
    # cal="1-2*((60-30+(-40/5)*(9-2*5/3+7/3*99/4*2998+10*568/14))-(-4*3)/(16-3*2))"
        cal=input("请输入计算公式:")
        if cal =="q":
            print("欢迎使用,再见!".center(50,"-"))
            exit()
        else:
            cal2=jisuan(cal)
            print("该运算最终值为:%s"%cal2)
            try:
                print("正确答案:%s"%eval(cal))
            except:
                print("正确答案:无法计算")
  • 相关阅读:
    nginx用户统计
    mysql用户和授权
    memcache操作
    nginx memcache缓存
    memcached安装启动
    Unity 菜单拓展
    用C#创建XML, XML格式化输出
    解析swf文件头,获取flash的原始尺寸
    kinematic与static刚体不会触发任何接触回调
    git使用
  • 原文地址:https://www.cnblogs.com/mstzkot/p/7201707.html
Copyright © 2020-2023  润新知