zoukankan      html  css  js  c++  java
  • 计算器

    功能需求:

    • 用户输入 1 - 2 * ( (60-30 +(-40/5) * (9-2*5/3 + 7 /3*99/4*2998 +10 * 568/14 )) - (-4*3)/ (16-3*2) )等类似公式后,必须自己解析里面的(),+,-,*,/符号和公式,运算后得出结果,结果必须与真实的计算器所得出的结果一致。

    • 实现加减乘除

    • 满足优先级

    所需知识点:

    1. 流程控制

    2. 函数

    3. 函数递归

    4. 正则表达式

    5. 常用数据类型列表的操作

    代码逻辑:

    wKioL1XAqR7hqRcKAAC8EP9u6Vo598.jpg

    详细代码:

    为了方便明白整个逻辑过程,代码中的好多调试信息没有去掉。

      1 #_*_coding:utf-8_*_
      2 __author__ = 'jieli'
      3 import re
      4 import sys
      5  
      6  
      7 def remove_space(data_list):
      8     '''去除列表中的空格元素'''
      9     for i in data_list:
     10         if type(i) is not int:
     11             if len(i.strip()) == 0:
     12                 data_list.remove(i)
     13     return  data_list
     14  
     15 def fetch_data_from_bracket(data_list,first_right_bracket_pos):
     16     '''用递归的形式取出每一对括号里的数据并进行运算且得出结果'''
     17     print 'data list:',data_list
     18  
     19     left_bracket_pos,right_bracket_pos = data_list.index('('),data_list.index(')') +1
     20     print '33[31;1mleft bracket pos:%s right_bracket_pos: %s33[0m' %(left_bracket_pos,first_right_bracket_pos)
     21     data_after_strip = data_list[left_bracket_pos:right_bracket_pos]
     22  
     23     if data_after_strip.count("(") > 1:
     24         print 'fetch_data_from_bracket:%s 33[31;1m%s33[0m left pos:%s'  %(data_after_strip,data_after_strip[1:] , left_bracket_pos)
     25         #return fetch_data_from_bracket(data_after_strip[left_bracket_pos+1:],first_right_bracket_pos)
     26         return fetch_data_from_bracket(data_after_strip[1:],first_right_bracket_pos)
     27  
     28     else:
     29         print 'last:',len(data_after_strip),data_after_strip
     30         bracket_start_pos = first_right_bracket_pos - len(data_after_strip) +1  # (takes two position
     31         calc_res = parse_operator(data_after_strip)
     32         return calc_res, bracket_start_pos,first_right_bracket_pos +1 #') takes one position'
     33 def parse_bracket(formula):  #解析空格中的公式
     34     '''解析空格中的公式,并运算出结果'''
     35     pattern = r"(.+)"
     36     m = re.search(pattern,formula) #匹配出所有的括号 ‘3 / 1      - 2 * ( (60-30 * (4-2)) - 4*3/ (6-3*2) )’ 匹配完之后是'( (60-30 * (4-2)) - 4*3/ (6-3*2) )'
     37     if m:
     38         data_with_brackets = m.group()
     39         #print list(data_with_brackets)
     40         data_with_brackets = remove_space(list(data_with_brackets))
     41         #print data_with_brackets
     42         calc_res = fetch_data_from_bracket(data_with_brackets,data_with_brackets.index(')'))
     43         print '33[32;1mResult:33[0m', calc_res
     44         print calc_res[1],calc_res[2]
     45         print  data_with_brackets[calc_res[1]:calc_res[2]]
     46         del data_with_brackets[calc_res[1]:calc_res[2]]
     47         data_with_brackets.insert(calc_res[1], str(calc_res[0])) #replace formula string with caculation result 4
     48         return parse_bracket(''.join(data_with_brackets)) #继续处理其它的括号
     49     else#no bracket in formula anymore
     50         print '33[42;1mCaculation result:33[0m' ,formula
     51  
     52 def caculate_1(formula): # for multiplication and division
     53     result = int(formula[0])  # e.g ['4', '/', '2', '*', '5'], loop start from '/'
     54     last_operator = None
     55     formula = list(formula)
     56     nagative_mark = False
     57     for index,i in enumerate(formula[1:]):
     58         if i.isdigit():
     59             if nagative_mark:
     60                 i = int('-'+i)
     61                 nagative_mark = False
     62             else:
     63                 i = int(i)
     64             #print '+++>',result,last_operator,i
     65             if last_operator == '*':
     66                 result  *= i
     67             elif last_operator == '/':
     68                 try:
     69                     result /= i
     70                 except ZeroDivisionError,e:
     71                     print "33[31;1mError:%s33[0m" % e
     72                     sys.exit()
     73         elif i == '-':
     74             nagative_mark = True
     75         else:
     76             last_operator = i
     77  
     78     print '乘除运算结果:' , result
     79     return result
     80 def caculate_2(data_list,operator_list):
     81     '''eg. data_list:['4', 3, 1372, '1']  operator_list:['-', '+', '-']'''
     82     data_list = remove_space(data_list)
     83     print 'caculater_2:',data_list,operator_list
     84     result = int(data_list[0])
     85     for i in data_list[1:]:
     86         if operator_list[0] == '+':
     87             result += int(i)
     88         elif operator_list[0] == '-':
     89             result -= int(i)
     90         del operator_list[0]
     91  
     92     print 'caculate_2 result:', result
     93     return  result
     94 def parse_operator(formula):
     95     print '开始运算公式:',formula
     96     formula = formula[1:-1] #remove bracket
     97  
     98     low_priorities = re.findall('[+,-]',''.join(formula))
     99     data_after_removed_low_priorities = re.split('[+,-]'''.join(formula))
    100     print '去掉加减后的公式列表,先算乘除:',data_after_removed_low_priorities
    101  
    102     for index,i in enumerate(data_after_removed_low_priorities):
    103         if i.endswith("*"or i.endswith("/") :
    104             data_after_removed_low_priorities[index] += '-' + data_after_removed_low_priorities[index+1]
    105             del data_after_removed_low_priorities[index+1]
    106     print '---------->handle nagative num:',data_after_removed_low_priorities
    107     #计算乘除运算
    108     nagative_mark = False
    109  
    110     for index,i in enumerate(data_after_removed_low_priorities):
    111         if not i.isdigit():
    112             if len(i.strip()) == 0:
    113                 nagative_mark = True
    114             else:#remove space
    115  
    116                 string_to_list = []
    117                 if nagative_mark:
    118                     prior_l = '-' + i[0]  #
    119                     nagative_mark = False
    120                 else:
    121                     prior_l = i[0]
    122                 for l in i[1:] :
    123                     if l.isdigit():
    124  
    125                         if prior_l.isdigit() or len(prior_l) >1: # two letter should be combined
    126                             prior_l += l
    127                         else:
    128                             prior_l = l
    129                     else# an operator * or /
    130  
    131                         string_to_list.append(prior_l)
    132                         string_to_list.append(l)
    133                         prior_l = l  #reset prior_l
    134                 else:
    135                     string_to_list.append(prior_l)
    136  
    137                 print '--->::', string_to_list
    138                 calc_res = caculate_1(string_to_list) #乘除运算结果
    139                 data_after_removed_low_priorities[index] = calc_res
    140                 #print '--->string to list:',string_to_list
    141                 #print '+>',index, re.split('[*,/]',i)
    142                 '''operators = re.findall('[*,/]',i)
    143                 data = re.split('[*,/]',i)
    144                 combine_to_one_list = map(None,data,operators)
    145                 combine_to_one_list =re.split("[[,],(,),'',None]", str(combine_to_one_list))
    146                 combine_to_one_list = ''.join(combine_to_one_list).split()
    147                 print '-->',combine_to_one_list
    148                 #print operators,data'''
    149             #caculate_1(combine_to_one_list)
    150         else :
    151             if nagative_mark:
    152                 data_after_removed_low_priorities[index] = '-' + i
    153     print '去掉* 和 /后开始运算加减:', data_after_removed_low_priorities,low_priorities
    154     #计算加减运算
    155     return caculate_2(data_after_removed_low_priorities,low_priorities)
    156     #print formula
    157 def main():
    158     while True:
    159         user_input = raw_input(">>>:").strip()
    160         if len(user_input) == 0:continue
    161         #parse_bracket(user_input)
    162         user_input = '(' + user_input + ')'
    163         #parse_bracket(' 1 - 2 * ( (60-30 +(-40/5) * (9-2*5/3 + 7 /3*99/4*2998 +10 * 568/14 )) - (-4*3)/ (16-3*2) ) ')
    164         parse_bracket(user_input)
    165  
    166         print '33[43;1mpython计算器运算结果:33[0m',eval(user_input)
    167 if __name__ == '__main__':
    168     main()

     

      1 #_*_coding:utf-8_*_
      2 import re
      3 def is_symbol(element):
      4     res=False
      5     symbol=['+','-','*','/','(',')']
      6     if element in symbol:
      7         res=True
      8     return res
      9 
     10 def priority(top_sym,wait_sym):
     11     # print('from the priotry : ',top_sym,wait_sym)
     12     level1=['+','-']
     13     level2=['*','/']
     14     level3=['(']
     15     level4=[')']
     16     #运算符栈栈顶元素为+-
     17     if top_sym in level1:
     18         # if wait_sym in level1:
     19         #     return '>'
     20         # elif wait_sym in level2: # top_sym='-' wait_sym='*'
     21         #     return '<'
     22         # elif wait_sym in level3: # top_sym='-' wait_sym='('
     23         #     return '<'
     24         # elif wait_sym in level4: # top_sym='-' wait_sym=')'
     25         #     return '>'
     26         # else:
     27         #     return '>'
     28         if wait_sym in level2 or wait_sym in level3:
     29             return '<'
     30         else:
     31             return '>'
     32 
     33     #运算符栈栈顶元素为*/
     34     elif top_sym in level2:
     35         # if wait_sym in level1:# top_sym='*' wait_sym='+'
     36         #     return '>'
     37         # elif wait_sym in level2:# top_sym='*' wait_sym='*'
     38         #     return '>'
     39         # elif wait_sym in level3:# top_sym='*' wait_sym='('
     40         #     return '<'
     41         # elif wait_sym in level4:# top_sym='*' wait_sym=')'
     42         #     return '>'
     43         # else:
     44         #     return '>'
     45         if wait_sym in level3:
     46             return '<'
     47         else:
     48             return '>'
     49 
     50     #运算符栈栈顶元素为(
     51     elif top_sym in level3:
     52         if wait_sym in level4: #右括号)碰到了(,那么左括号应该弹出栈
     53             return '='
     54         else:
     55             return '<'  #只要栈顶元素为(,等待入栈的元素都应该无条件入栈
     56     #运算符栈栈顶元素为)
     57 
     58 def calculate(num1,symbol,num2):
     59     res=0
     60     if symbol == '+':
     61         res=num1+num2
     62     elif symbol == '-':
     63         res=num1-num2
     64     elif symbol == '*':
     65         res=num1*num2
     66     elif symbol == '/':
     67         res=num1/num2
     68     print('from calculate res is [%s|%s|%s] %s' %(num1,symbol,num2,res))
     69     return res
     70 
     71 def init_action(expression):
     72     # print(expression)
     73     expression=re.sub(' ','',expression)
     74     # print(expression)
     75     init_l=[i for i in re.split('(-d+.*d*)',expression) if i]
     76     # print('--->',init_l)
     77     expression_l=[]
     78     while True:
     79         if len(init_l) == 0:break
     80         exp=init_l.pop(0)
     81         # print('==>',exp)
     82         if len(expression_l) == 0 and re.search('^-d+.*d*$',exp):
     83             expression_l.append(exp)
     84             continue
     85         if len(expression_l) > 0:
     86             if re.search('[+-*/(]$',expression_l[-1]):
     87                 expression_l.append(exp)
     88                 continue
     89 
     90         new_l=[i for i in re.split('([+-*/()])',exp) if i]
     91         expression_l+=new_l
     92         # print(expression_l)
     93     return expression_l
     94 
     95 def main(expression_l):
     96     # print('from in the main',expression_l)
     97     number_stack=[]
     98     symbol_stack=[]
     99     for ele in expression_l:
    100         print('-'*20)
    101         print('数字栈',number_stack)
    102         print('运算符栈',symbol_stack)
    103         print('待入栈运算符',ele)
    104 
    105         ret=is_symbol(ele)
    106         if not ret:
    107             #压入数字栈
    108             ele=float(ele)
    109             number_stack.append(ele)
    110         else:
    111             #压入运算符栈
    112             while True:
    113                 if len(symbol_stack) == 0:
    114                     symbol_stack.append(ele)
    115                     break
    116                 res=priority(symbol_stack[-1],ele)
    117 
    118                 if res == '<':
    119                     symbol_stack.append(ele)
    120                     break
    121                 elif res == '=':
    122                     symbol_stack.pop()
    123                     break
    124                 elif res == '>':
    125                     symbol=symbol_stack.pop()
    126                     num2=number_stack.pop()
    127                     num1=number_stack.pop()
    128                     number_stack.append(calculate(num1,symbol,num2))
    129 
    130     else:
    131         symbol=symbol_stack.pop()
    132         num2=number_stack.pop()
    133         num1=number_stack.pop()
    134         number_stack.append(calculate(num1,symbol,num2))
    135 
    136     return number_stack,symbol_stack
    137 
    138 if __name__ == '__main__':
    139     expression='-1 - 2 *((-60+30+(-40/5)*(-9-2*-5/30-7/3*99/4*2998+10/-568/14))-(-4*-3)/(16-3*2))+3'
    140     # expression='(1-2*3)-1-2*((-60+30+(-40/5)*(-9-2*-5/30-7/3*99/4*2998+10*568/14))-(-4*-3)/(16-3*2))+3'
    141     # expression='-1 -3*( -2+3)'
    142     expression_l=init_action(expression)
    143 
    144     # print(expression_l)
    145 
    146     l=main(expression_l)
    147     # print('====>',l)
    148     print('最终结果是:%s' %l[0][0])
  • 相关阅读:
    EasyUI中datagrid的行编辑模式中,找到特定的Editor,并为其添加事件
    easyui datagrid plunges 扩展 插件
    jQuery EasyUI DataGrid Checkbox 数据设定与取值
    Easyui Tree方法扩展
    记账凭证
    部分扩展功能总结
    凭证
    voucer
    Box2D 一、学习资料(库、pdf)
    EUI EXML内部类Skin和ItemRenderer
  • 原文地址:https://www.cnblogs.com/wangmo/p/6111828.html
Copyright © 2011-2022 走看看