python实现计算器
2016-05-22 19:55
471 查看
计算器功能
实现优先级解析,加减乘除四则运算自定义小数位精度
实现思想:
先找到最里层括号,根据乘除,加减优先级,调用写好的乘除、加减运算函数算出括号内总值,再将原括号式用所得值替换,此过程循环进行,直到去除所有括号,得到一个只剩加减乘除的运算式。再次调用乘除加减函数算出结果。
实现方法:
正则匹配出最里层括号括号内先算乘除后算加减,算出结果替换原括号字符串,循环执行
乘除:正则匹配出 ([-]num1) ([*/]) ([-]num2) 分组,findall查找得到 [('2', '*', '3'), ('5', '/', '3')]列表,计算元组内值替换原字符串,循环执行,直到去除所有乘除法
加减:正则匹配出 ([-]num1)([+-])(num2)分组,由于符号‘-’和负号相同,带符号匹配用findall方法一次匹配出所有会出现符号混乱问题;用search每次都是从头匹配只可能出现
[-]num1 +- num2 情况,再根据分组可以直接拿到[-]num1,num2和运算符号,把结果计算出来替换原字符串,循环执行。
将最后得到的只有加减乘除的运算式再进行 乘除 加减 运算,得出最后计算结果。
代码
#!/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.
相关文章推荐
- python zip( )函数
- python核心编程2
- 【Python】使用cmd模块构造一个带有后台线程的交互命令行界面
- Python面向对象编程-封装
- pyenv 环境构造多python环境
- Python调用R语言
- python 进行文本相似性对比
- 用python写一个简单的推荐系统
- Python函数及使用函数进行面向过程封装
- Python_1_数据类型及变量
- python 有道翻译
- pgloader
- python学习03-数字
- 一个纯小白的安装python库的郁闷之旅
- Python 资源大全中文版
- python3 module中__init__.py的需要注意的地方
- Python开发轻量级爬虫
- wxPython学习笔记(二)
- python-scrapy-爬取图片笔记
- Wooyun最新确认漏洞爬虫V0.02