该计算器主要分为四个模块:

weclome_func函数用来进入界面获取表达式,并判断表达式是否正确,然后返回表达式;

add_sub函数用来进行加减运算,如果有多个加减运算,会递归,最后返回对应的值

multi_divide函数用来进行乘除运算,如果有多个乘除运算,会递归,最后返回对应的值

del_bracket函数用来去除小括号及调用multi_divide和add_sub函数,如果存在多个括号,也会实现递归。

代码如下:

#! /usr/bin/env python3

import sys
import re def welcome_func():
flag_exit = True
welcome_str = "超级计算器"
print(welcome_str.center(50, "*"), '\n')
while flag_exit:
exp = input("请输入要计算的表达式[q:退出]: ").strip()
if exp == "q":
flag_exit = False
elif len(exp) == 0:
continue
else:
exp = re.sub("\s*", '', exp) ## 取出空格
return exp def multi_divide(expression):
val = re.search("\d+\.?\d*[*/][+-]?\d+\.?\d*", expression) ##匹配乘除号,如192.168*-1.99
if not val: # 乘除号不存在,返回输入的表达式
return expression
data = re.search("\d+\.?\d*[*/][+-]?\d+\.?\d*", expression).group()
if len(data.split('*')) > 1: # 当可以用乘号分割,证明有乘法运算
part1, part2 = data.split('*') # 用除号分割
value = float(part1) * float(part2)
else:
part1, part2 = data.split('/')
if float(part2) == 0: # 如果分母为0,则退出计算
sys.exit("计算过程中有被除数为0的存在,计算表达式失败!")
value = float(part1) / float(part2) s1, s2 = re.split("\d+\.?\d*[*/][+-]?\d+\.?\d*", expression, 1) # 分割表达式
next_expression = "%s%s%s" % (s1, value, s2)
return multi_divide(next_expression) # 递归表达式 def add_sub(expression):
expression = expression.replace('+-', '-') # 替换表达式里的所有‘+-‘
expression = expression.replace('--', '+') # 替换表达式里的所有‘--‘
expression = expression.replace('-+', '-') # 替换表达式里的所有‘-+‘
expression = expression.replace('++', '+') # 替换表达式里的所有‘++‘ data = re.search('\d+\.?\d*[+-]\d+\.?\d*', expression) # 匹配加减号
if not data: # 如果不存在加减号,则证明表达式已计算完成,返回最终结果
return expression
val = re.search('[+-]?\d+\.?\d*[+-]\d+\.?\d*', expression).group()
if len(val.split('+')) > 1: # 以加号分割成功,有加法计算
part1, part2 = val.split('+')
value = float(part1) + float(part2)
elif val.startswith('-'): # 如果是已‘-‘开头则需要单独计算
part1, part2, part3 = val.split('-')
value = -float(part2) - float(part3) # 计算以负数开头的减法
else:
part1, part2 = val.split('-')
value = float(part1) - float(part2) s1, s2 = re.split('[+-]?\d+\.?\d*[+-]\d+\.?\d*', expression, 1) # 分割表达式
next_expression = "%s%s%s" % (s1, value, s2)
return add_sub(next_expression) # 递归运算表达式 def del_bracket(expression): ## [^()]+ 匹配除了括号以外的任意字符 if not re.search(r"\([^()]+\)", expression): # 判断小括号,如果不存在小括号,直接调用乘除,加减计算
ret1 = multi_divide(expression)
ret2 = add_sub(ret1)
return ret2 # 返回最终计算结果
data = re.search(r"\([^()]+\)", expression).group() # 如果有小括号,匹配出优先级最高的小括号
print("获取表达式", data)
data = data.strip('[\(\)]') # 剔除小括号
ret1 = multi_divide(data)
# print("全部乘除计算完后的表达式:", ret1)
ret2 = add_sub(ret1)
# print("全部加减计算结果:", ret2)
part1, part2 = re.split(r"\([^()]+\)", expression, 1) # 分割表达式
expression = "%s%s%s" % (part1, ret2, part2)
return del_bracket(expression) # 递归去小括号 if __name__ == "__main__":
try:
expression = welcome_func() ## 获取表达式
print(expression)
result = eval(expression) ## 用eval来验证
print(result)
ret = del_bracket(expression) ## 用函数计算得出结果
result = float(result)
ret = float(ret)
print("eval计算结果: ", result)
print("表达式计算结果: ", ret)
except (SyntaxError, ValueError, TypeError):
print("输入表达式不合法,请检查!")

python 利用正则构建一个计算器的更多相关文章

  1. python 利用栈实现复杂计算器

    #第五周的作业--多功能计算器#1.实现加减乘除及括号的优先级的解析,不能使用eval功能,print(eval(equation))#2.解析复杂的计算,与真实的计算器结果一致#用户输入 1 - 2 ...

  2. 利用 vue-cli 构建一个 Vue 项目

    一.项目初始构建 现在如果要构建一个 Vue 的项目,最方便的方式,莫过于使用官方的 vue-cli . 首先,咱们先来全局安装 vue-cli ,打开命令行工具,输入以下命令: $ npm inst ...

  3. 利用Dockerfile构建一个基于CentOS 7镜像

    利用Dockerfile构建一个基于CentOS 7,包括java 8, tomcat 7,php ,mysql+mycat的镜像. Dockerfile内容如下: FROM centosMAINTA ...

  4. 利用ELK构建一个小型的日志收集平台

    利用ELK构建一个小型日志收集平台 伴随着应用以及集群的扩展,查看日志的方式总是不方便,我们希望可以有一个便于我们查询及提醒功能的平台:那么首先需要剖析有几步呢? 格式定义 --> 日志收集 - ...

  5. 利用maven构建一个spring mvc的helloworld实例

    刚开始学习maven和spring mvc,学的云里雾里的 这里提供一个hello world实例,记录自己的学习之路 首先看maven官网的介绍 Apache Maven is a software ...

  6. 利用Dockerfile构建一个基于centos 7,包括java 8, tomcat 7,php ,mysql+mycat的镜像

    Dockerfile内容如下: FROM centos MAINTAINER Victor ivictor@foxmail.com WORKDIR /root RUN rm -f /etc/yum.r ...

  7. 利用Roslyn构建一个简单的C#交互脚本引擎

    (此文章同时发表在本人微信公众号"dotNET每日精华文章",欢迎右边二维码来关注.) 微软的下一代编译器技术Roslyn是一个里程碑的技术,可以给.NET平台带来无限想象空间.比 ...

  8. Python - 利用flask搭建一个共享服务器

    零.概述 我利用flask搭建了一个简易的共享服务器,分享给大家 一.python代码 import os import time from flask import Flask,render_tem ...

  9. python利用socket写一个文件上传

    1.先将一张图片拖入‘文件上传’的目录下,利用socket把这张图片写到叫‘yuan’的文件中 2.代码: #模拟服务端 import subprocess import os import sock ...

随机推荐

  1. shell脚本学习总结08--比较与测试

    程序中流程控制是由比较语句和测试语句处理的 算数比较 [ $var -gt 20 ] [ $var -gt 20 -a $var -lt 50 ]         #使用逻辑与 [ $var -ne ...

  2. onTouch事件分发

    事件机制 我们知道view中有onTouch,onClick, 1.并且onTouch优先于onClick执行, 2.onTouch有返回值,为true时onClick并不再执行了 因为一切VIew都 ...

  3. Socket通信编程实例(SIB和SS'SOB)

    客户端: package socket; import java.io.BufferedReader; import java.io.IOException; import java.io.Input ...

  4. MFC中控件的TAB顺序

    本文来自: http://hi.baidu.com/qingcaichongch/item/47f7ae14de8cbef6ddeeca42 在MFC中添加控件后,按Ctrl+d可以改变控件TAB顺序 ...

  5. 桌面不显示IE图标解决方法

    如果你的是WIN7,恰好你的桌面上IE图标不知道怎么被搞咩了. 向这里看过来,这里有一个文件你正好能用上. 使用方法很简单: 猛戳下载,猛戳两下安装 下载解决

  6. 170310、Jenkins部署Maven多环境项目(dev、beta、prod)的参数设置

    使用Jenkins配置Git+Maven的自动化构建: http://blog.csdn.net/xlgen157387/article/details/50353317 在一个多开发和生产环境的项目 ...

  7. Socket连接何时需要断开

    socket连接没有正常断开,导致无法下次无法进行连接.

  8. 论OI中无穷大(INF)的取值

    水 为什么我的Floyd会输出负数啊? 为什么我的代码写对了却全都爆零了啊? 那么很可能是你的INF取大/小了! 那么inf到底应该取什么值呢? 首先,inf应该要比一般的题目中出现的数据要大,但是又 ...

  9. 关于ios7 UINavigationController.interactivePopGestureRecognizer手势集成

    因为公司业务需求,结合网上的资料整理了一下. 如果自定义过navbar的leftbarbutton 或者backbarbutton 原生interactivePopGestureRecognizer默 ...

  10. 关于VFS文件系统中的superblock、inode、d_entry和file数据结构