• module022计算器


    需求

    • 实现加减乘除及扩号优先级解析
    • 用户输入 1 - 2 * ( (60-30 +(-40/5) * (9-2*5/3 + 7 /3*99/4*2998 +10 * 568/14 )) - (-4*3)/ (16-3*2) )等类似公式后,必须自己解析里面的(),+,-,*,/符号和公式(不能调用eval等类似功能偷懒实现),运算后得出结果,结果必须与真实的计算器所得出的结果一致

    代码

      1 #! /usr/bin/env python3
      2 # -*- coding:utf-8 -*-
      3 # Author:Jailly
      4 
      5 import re
      6 
      7 # 匹配单次加减运算表达式的re编译对象
      8 sub_pm = re.compile(r'''
      9 \s*
     10 (?P<operand1>((-?[1-9]\d*)|0)(\.\d+)?)  # 第一个操作数
     11 \s*
     12 (?P<operator>[+-])  # 操作符
     13 \s*
     14 (?P<operand2>((-?[1-9]\d*)|0)(\.\d+)?)  # 第二个操作数
     15 ''', re.X)
     16 
     17 # 匹配单次乘除运算表达式的re编译对象
     18 sub_md = re.compile('''
     19     \s*
     20     (?P<operand1>((-?[1-9]\d*)|0)(\.\d+)?)  # 第一个操作数
     21     \s*
     22     (?P<operator>[*/])  # 操作符
     23     \s*
     24     (?P<operand2>((-?[1-9]\d*)|0)(\.\d+)?)  # 第二个操作数
     25 ''',re.X)
     26 
     27 
     28 def pm(exp):
     29     '''
     30     最底层的加减,无乘除,无括号
     31     :param exp:只含有加减的运算式字符串
     32     :param sub_pm:匹配单次加减运算表达式的re编译对象
     33     :return:递归返回将逐次运算结果代入原式后的表达式
     34     '''
     35 
     36     sub_exp = sub_pm.search(exp)
     37 
     38     if sub_exp:
     39         operand1 = float(sub_exp.group('operand1'))
     40         operand2 = float(sub_exp.group('operand2'))
     41         res = ( operand1 + operand2 ) if sub_exp.group('operator') == '+' else ( operand1 - operand2 )
     42 
     43         # 从左到右计算,只取匹配到的第一个替换,count = 1
     44         new_exp = sub_pm.sub(str(res),exp,count=1)
     45 
     46         return pm(new_exp)
     47 
     48     else:
     49         return exp
     50 
     51 
     52 def md(exp):
     53     '''
     54     最底层的乘除,可有加减,但无括号
     55     :param exp:只含有乘除的运算式字符串
     56     :return:递归返回将逐次运算结果代入原式后的表达式
     57     '''
     58     sub_exp = sub_md.search(exp)
     59 
     60     if sub_exp:
     61         operand1 = float(sub_exp.group('operand1'))
     62         operand2 = float(sub_exp.group('operand2'))
     63         res = ( operand1 * operand2 ) if sub_exp.group('operator') == '*' else ( operand1 / operand2 )
     64 
     65         # 从左到右计算,只取匹配到的第一个替换,count = 1
     66         new_exp = sub_md.sub(str(res),exp,count=1)
     67 
     68         return md(new_exp)
     69     else:
     70         return exp
     71 
     72 
     73 def brackets(exp):
     74     '''
     75     供brackets2调用,计算括号内的运算式
     76     :param exp:只含有单层括号的运算式字符串
     77     :return:运算结果的字符串形式
     78     '''
     79 
     80     exp1 = md(exp)
     81     exp2 = pm(exp1)
     82 
     83     res = re.search(r'\((?P<res>.+)\)',exp2).group('res')
     84     
     85     return res
     86 
     87 def brackets2(exp):
     88     '''
     89     多层括号运算
     90     :param exp:含有多层括号的运算式字符串
     91     :return:
     92     '''
     93     min_bra_c = re.compile(r'\([^()]+\)')
     94     min_bra_m = min_bra_c.search(exp)
     95 
     96     if min_bra_m:
     97         min_bra_exp = min_bra_m.group()
     98         res = brackets(min_bra_exp)
     99         new_exp = min_bra_c.sub(res,exp,count=1)
    100 
    101         return brackets2(new_exp)
    102     else:
    103         return exp
    104 
    106 
    107 def calc(exp):
    108     '''主程序'''
    109 
    110     exp1 = brackets2(exp)
    111     exp2 = md(exp1)
    112     exp3 = pm(exp2)
    113 
    114     return float(exp3)
    115 
    116 
    117 if __name__ == '__main__':
    118 
    119     while 1:
    120         q = input('请输入您的运算式:')
    121         if q == 'q':
    122             exit()
    123         else:
    124             try:
    125                 print('结果为:\033[1;31m %s \033[0m'%str(calc(q)))
    126             except:
    127                 print('\033[1;31m请输入正确的运算式!\033[0m')
  • 相关阅读:
    怎样在ASP.NET中使用VB.NET上传大文件
    准备开始研读petShop
    Documentum常见问题9—导航树的一些常见设置
    [转]CMMI 入门 基本术语:约束、假设、依赖、风险、承诺
    MyEclipse 8.6反编译插件安装
    Documentum常见问题7—为客户化Type类型Import时添加自定义属性
    【自省篇】程序员的十大技术烦恼
    Documentum常见问题10修改特定Type的显示图标
    打发时间的题目,每天做一点
    Documentum常见问题8—限制导航树上的文件夹个数
  • 原文地址:https://www.cnblogs.com/jailly/p/6917232.html
Copyright © 2020-2023  润新知