zoukankan      html  css  js  c++  java
  • python实现计算器

    计算器功能

    • 实现优先级解析,加减乘除四则运算
    • 自定义小数位精度

    实现思想:

    • 先找到最里层括号,根据乘除,加减优先级,调用写好的乘除、加减运算函数算出括号内总值,再将原括号式用所得值替换,此过程循环进行,直到去除所有括号,得到一个只剩加减乘除的运算式。
    • 再次调用乘除加减函数算出结果。

    实现方法:

    1. 正则匹配出最里层括号
    2. 括号内先算乘除后算加减,算出结果替换原括号字符串,循环执行
      乘除:正则匹配出 ([-]num1) ([*/]) ([-]num2) 分组,findall查找得到 [('2', '*', '3'), ('5', '/', '3')]列表,计算元组内值替换原字符串,循环执行,直到去除所有乘除法
      加减:正则匹配出 ([-]num1)([+-])(num2)分组,由于符号‘-’和负号相同,带符号匹配用findall方法一次匹配出所有会出现符号混乱问题;用search每次都是从头匹配只可能出现
      [-]num1 +- num2 情况,再根据分组可以直接拿到[-]num1,num2和运算符号,把结果计算出来替换原字符串,循环执行。
    3. 将最后得到的只有加减乘除的运算式再进行 乘除 加减 运算,得出最后计算结果。

    代码

    #!/usr/bin/env python
    # -*-coding:utf-8 -*-
    import re
    #乘除运算
    def mult(args):
        pat = re.compile(r'[-+]?(-?d+.?d*)([*/])(-?d+.?d*)')  #取出 [-]a*[-]b 或 [-]a/[-]b
        while pat.search(args):                         #有符合条件的程序就一直执行,直到匹配不到返回None
            m = pat.findall(args)                        #[('2', '*', '3'), ('5', '/', '3'), ('40', '*', '4'), ('3', '/', '5'), ('6', '*', '3')]
            for tup in m:                               #循环列表里的元组进行计算,再用结果替换原式中对应的值 如用结果 6 替换 2*3
                num1,symbol,num2 = tup
                if symbol == '*':
                    result = float(num1) * float(num2)
                elif symbol == '/':
                    result = float(num1) / float(num2)
                args = args.replace(num1+symbol+num2, str(result), 1)
        return args
    
    #加减运算
    def com(args):
        args = args.replace('--', '+')          #将计算过程中出现的不规则运算符替换
        args = args.replace('-+', '-')
        args = args.replace('+-', '-')
        args = args.replace('++', '+')
        pat = re.compile(r'(-?d+.?d*)([-+])(d+.?d*)')    #查找  [-]a +- b ,并对 数字 和 运算符号分组
        while pat.search(args):
            m = pat.search(args)
            num = m.group()
            num1 = float(m.group(1))       # 第一个数字
            symbol = m.group(2)            # 运算符号
            num3 = float(m.group(3))       #第二个数字
    
            if symbol == '-':               #计算结果并替换原串中对应的值 如,用 结果 6 替换 2+3
                result = num1 - num3
            elif symbol == '+':
                result = num1 + num3
            args = args.replace(num, str(result), 1)
        return args
    
    #取括号并进行括号内加减运算
    def bracket(value):
        pat = re.compile(r'([^()]*)')         #取括号
        while pat.search(value):                #有符合条件的就一直循环,直到返回None时结束
            m = pat.search(value)
            # print(m.group())
            res = m.group()
            res_mult = mult(res)                #括号内乘除法运算
            res_mult = res_mult.strip('(').strip(')')  #去 两边 ()号
            result = com(res_mult)              #加减运算
            value = value.replace(res,result,1)  #替换
            # print(value)
        return value
    
    #source = "1 - 2 *  ( (60-30 +(-9-2-5-2*3-5/3-40*4/2-3/5+6*3) * (-9-2-5-2*5/3 + 7 /3*99/4*2998 +10 * 568/14 )) - (-4*3)/ (16-3*2) )"
    print(
    '''
    使用方法:
        1)退出程序:
        按q|Q退出
        2)设置精度(默认取整):
        sales = NUM (设置小数精度,使用方法:在操作计算提示符后输入 sales = NUM(NUM必须是正整数))
    ''')
    NUM = None
    while True:                                                             #计算,可设置精度
        source = input('操作计算:')
        source = re.sub(r' ', '', source)
    
        if source == 'q' or source == 'Q':                                  #是否退出判断
            print('程序退出!!!')
            break
    
        if not re.findall(r'd*.?d*[+-*/]d*.?d*', source):         #如果不是计算式
            if 'sales=' in source and source[6].isdigit():                  #如果输入符合设置精度的要求
                NUM = int(re.split(r'sales=', source)[1])                   #将精度位数值赋给 NUM,返回输入计算式
                continue
            else:                                                           #输入不符合条件不做处理,返回重新输入
                continue
    
        finn = com(mult(bracket(source)))    #bracket()为去除括号后的结果,再对其进行先乘除后加减运算
        print('结果:', round(float(finn), NUM))
    
    

    片段解析:

    加减运算部分:

    def com(args):
        '''
        去括号之后会出现原括号外符号和括号内符号紧临的情况,要先符号合并;加减运算在乘除运算完之后进行
        '''
        args = args.replace('--', '+')          #将计算过程中出现的不规则运算符替换
        args = args.replace('-+', '-')
        args = args.replace('+-', '-')
        args = args.replace('++', '+')
    
        '''
        匹配 ([-]num1) (+-) (num2) 并对数字和符号分组;
        所有运算都是带符号运算
        '''
        pat = re.compile(r'(-?d+.?d*)([-+])(d+.?d*)')    #查找  [-]a +- b ,并对 数字 和 运算符号分组
    
        '''
        pat.search(string) 正则匹配有结果返回一个对象,为真;匹配不到返回 None,为假。
        用匹配结果作循环条件
        '''
        while pat.search(args):				
            m = pat.search(args)		   #匹配出第一个符合条件的字符串
            num = m.group()
            num1 = float(m.group(1))       # 取出分组中的第一个数字
            symbol = m.group(2)            # 取出运算符号
            num3 = float(m.group(3))       # 取出第二个数字
    
            if symbol == '-':               #判断symbol是 '-'还是'+' 计算结果
                result = num1 - num3
            elif symbol == '+':
                result = num1 + num3
            args = args.replace(num, str(result), 1)	#用计算结果替换原串中对应的字符串 如,用结果 5.0 替换 2+3
        return args
    

    自定义小数位精度

    使用 round(round(number, ndigits=None) 用户可自定义 ndigits.
    




  • 相关阅读:
    新东西-intel edison
    MFC AfxMessageBox(_T("Please Load Rawdata First !"));
    libgl1-mesa-glx:i386 : 依赖: libglapi-mesa:i386
    开源硬件_瑞芯微开发板
    手机方案商
    嵌入式Linux应用开发__求职要求
    工作要求
    Proc文件系统接口调试
    Sysfs文件系统接口调试
    Ubuntu Linux 解决 bash ./ 没有那个文件或目录 的方法
  • 原文地址:https://www.cnblogs.com/yangxiaolan/p/5517594.html
Copyright © 2011-2022 走看看