文档章节

python 计算器

eddy_linux
 eddy_linux
发布于 2015/11/09 15:16
字数 1170
阅读 374
收藏 1

码上生花,ECharts 作品展示赛正式启动!>>>

#!/usr/bin/env python
# -*- coding:utf-8 -*-
"""
该计算器思路:
    1、递归寻找表达式中只含有 数字和运算符的表达式,并计算结果
    2、由于整数计算会忽略小数,所有的数字都认为是浮点型操作,以此来保留小数
使用技术:
    1、正则表达式
    2、递归(python中递归返回值是None,这点是坑)
 
执行流程如下:
******************** 请计算表达式: 1 - 2 * ( (60-30 +(-40.0/5) * (9-2*5/3 + 7 /3*99/4*2998 +10 * 568/14 )) - (-4*3)/ (16-3*2) ) ********************
before: ['1-2*((60-30+(-40.0/5)*(9-2*5/3+7/3*99/4*2998+10*568/14))-(-4*3)/(16-3*2))']
-40.0/5=-8.0
after: ['1-2*((60-30+-8.0*(9-2*5/3+7/3*99/4*2998+10*568/14))-(-4*3)/(16-3*2))']
========== 上一次计算结束 ==========
before: ['1-2*((60-30+-8.0*(9-2*5/3+7/3*99/4*2998+10*568/14))-(-4*3)/(16-3*2))']
9-2*5/3+7/3*99/4*2998+10*568/14=173545.880953
after: ['1-2*((60-30+-8.0*173545.880953)-(-4*3)/(16-3*2))']
========== 上一次计算结束 ==========
before: ['1-2*((60-30+-8.0*173545.880953)-(-4*3)/(16-3*2))']
60-30+-8.0*173545.880953=-1388337.04762
after: ['1-2*(-1388337.04762-(-4*3)/(16-3*2))']
========== 上一次计算结束 ==========
before: ['1-2*(-1388337.04762-(-4*3)/(16-3*2))']
-4*3=-12.0
after: ['1-2*(-1388337.04762--12.0/(16-3*2))']
========== 上一次计算结束 ==========
before: ['1-2*(-1388337.04762--12.0/(16-3*2))']
16-3*2=10.0
after: ['1-2*(-1388337.04762--12.0/10.0)']
========== 上一次计算结束 ==========
before: ['1-2*(-1388337.04762--12.0/10.0)']
-1388337.04762--12.0/10.0=-1388335.84762
after: ['1-2*-1388335.84762']
========== 上一次计算结束 ==========
我的计算结果: 2776672.69524
"""
 
 
import re
 
 
def compute_mul_div(arg):
    """ 操作乘除
    :param expression:表达式
    :return:计算结果
    """
 
    val = arg[0]
    mch = re.search('\d+\.*\d*[\*\/]+[\+\-]?\d+\.*\d*', val)
    if not mch:
        return
    content = re.search('\d+\.*\d*[\*\/]+[\+\-]?\d+\.*\d*', val).group()
 
    if len(content.split('*'))>1:
        n1, n2 = content.split('*')
        value = float(n1) * float(n2)
    else:
        n1, n2 = content.split('/')
        value = float(n1) / float(n2)
 
    before, after = re.split('\d+\.*\d*[\*\/]+[\+\-]?\d+\.*\d*', val, 1)
    new_str = "%s%s%s" % (before,value,after)
    arg[0] = new_str
    compute_mul_div(arg)
 
 
def compute_add_sub(arg):
    """ 操作加减
    :param expression:表达式
    :return:计算结果
    """
 
    arg[0] = arg[0].replace('+-','-')
    arg[0] = arg[0].replace('++','+')
    arg[0] = arg[0].replace('-+','-')
    arg[0] = arg[0].replace('--','+')
 
    if arg[0].startswith('-'):
        arg[1] += 1
        arg[0] = arg[0].replace('-','&')
        arg[0] = arg[0].replace('+','-')
        arg[0] = arg[0].replace('&','+')
        arg[0] = arg[0][1:]
    val = arg[0]
    mch = re.search('\d+\.*\d*[\+\-]{1}\d+\.*\d*', val)
    if not mch:
        return
    content = re.search('\d+\.*\d*[\+\-]{1}\d+\.*\d*', val).group()
    if len(content.split('+'))>1:
        n1, n2 = content.split('+')
        value = float(n1) + float(n2)
    else:
        n1, n2 = content.split('-')
        value = float(n1) - float(n2)
 
    before, after = re.split('\d+\.*\d*[\+\-]{1}\d+\.*\d*', val, 1)
    new_str = "%s%s%s" % (before,value,after)
    arg[0] = new_str
    compute_add_sub(arg)
 
 
def compute(expression):
    """ 操作加减乘除
    :param expression:表达式
    :return:计算结果
    """
    inp = [expression,0]
 
    # 处理表达式中的乘除
    compute_mul_div(inp)
 
    # 处理
    compute_add_sub(inp)
    if divmod(inp[1],2)[1] == 1:
        result = float(inp[0])
        result = result * -1
    else:
        result = float(inp[0])
    return result
 
 
def exec_bracket(inp_list):
    """ 递归处理括号,并计算
    :param expression: 表达式
    :return:最终计算结果
    """
    # 如果表达式中已经没有括号,则直接调用负责计算的函数,将表达式结果返回,如:2*1-82+444
    if not re.search('\(([\+\-\*\/]*\d+\.*\d*){2,}\)', inp_list[0]):
        final = compute(inp_list[0])
        inp_list[0] = final
        return inp_list
    # 获取 第一个 只含有 数字/小数 和 操作符 的括号
    # 如:
    #    ['1-2*((60-30+(-40.0/5)*(9-2*5/3+7/3*99/4*2998+10*568/14))-(-4*3)/(16-3*2))']
    #    找出:(-40.0/5)
    content = re.search('\(([\+\-\*\/]*\d+\.*\d*){2,}\)', inp_list[0]).group()
 
    # 分割表达式,即:
    # 将['1-2*((60-30+(-40.0/5)*(9-2*5/3+7/3*99/4*2998+10*568/14))-(-4*3)/(16-3*2))']
    # 分割更三部分:['1-2*((60-30+(    (-40.0/5)      *(9-2*5/3+7/3*99/4*2998+10*568/14))-(-4*3)/(16-3*2))']
    before, nothing, after = re.split('\(([\+\-\*\/]*\d+\.*\d*){2,}\)', inp_list[0], 1)
 
    print 'before:',inp_list
    content = content[1:len(content)-1]
 
    # 计算,提取的表示 (-40.0/5),并活的结果,即:-40.0/5=-8.0
    ret = compute(content)
 
    print '%s=%s' %( content, ret)
 
    # 将执行结果拼接,['1-2*((60-30+(      -8.0     *(9-2*5/3+7/3*99/4*2998+10*568/14))-(-4*3)/(16-3*2))']
    inp_list[0] = "%s%s%s" %(before, ret, after)
    print 'after:',inp_list
    print "="*10,'上一次计算结束',"="*10
 
    # 循环继续下次括号处理操作,本次携带者的是已被处理后的表达式,即:
    # ['1-2*((60-30+   -8.0  *(9-2*5/3+7/3*99/4*2998+10*568/14))-(-4*3)/(16-3*2))']
 
    # 如此周而复始的操作,直到表达式中不再含有括号
    exec_bracket(inp_list)
 
 
 
# 使用 __name__ 的目的:
#   只有执行 python index.py 时,以下代码才执行
#   如果其他人导入该模块,以下代码不执行
if __name__ == "__main__":
    print '*'*20,"请计算表达式:", "1 - 2 * ( (60-30 +(-40.0/5) * (9-2*5/3 + 7 /3*99/4*2998 +10 * 568/14 )) - (-4*3)/ (16-3*2) )" ,'*'*20
    inpp = '1 - 2 * ( (60-30 +(-40.0/5) * (9-2*5/3 + 7 /3*99/4*2998 +10 * 568/14 )) - (-4*3)/ (16-3*2) ) '
    inpp = re.sub('\s*','',inpp)
    # 由于python的递归的坑,所有要把表达式保存在列表中
    inp_list = [inpp,]
    exec_bracket(inp_list)
    final = inp_list[0]
    print "我的计算结果:",final
    print "eval计算结果(正是计算器不可取):",eval('1 - 2 * ( (60-30 +(-40.0/5) * (9-2*5/3 + 7 /3*99/4*2998 +10 * 568/14 )) - (-4*3)/ (16-3*2) ) ')


© 著作权归作者所有

eddy_linux
粉丝 22
博文 135
码字总数 188789
作品 0
成都
程序员
私信 提问
加载中
请先登录后再评论。
ArcGIS 字段计算器 Python 坑

最近要处理个简单数据,一个字段中为文本类型,包含各种描述。要求是包含平方米的数值提取出来,变成数值,如果包含多个,则把各个值累加起来。 比如 字段值为 “非法占用100平方米” 处理后...

osc_n41kxg36
2019/07/09
7
0
Python入门的三大问题和三大谎言

Python广告,铺天盖地,小白们雾里看花,Python无限美好。作为会20几种语言(BASIC Foxbase/pro VB VC C C++ c# js typescript HTML ArduinoC Delphi VBA VB 汇编 scratch java swift python ...

osc_ikbuen62
04/16
7
0
基于ArcGIS的python编程 18、在字段计算器中使用Python脚本 - 知乎

很久没有更新专栏了,趁着五一劳动节,刚好有时间“劳动”一下,更新一下专栏的文章。接下来的文章是关于在ArcMap中的字段计算器中使用Python脚本;字段计算器中可以使用的脚本有两种,分别是...

基于ArcGIS的python编程
2019/10/21
0
0
PyQt学习随笔:槽函数获取信号发送对象的方法

案例: 设计一个计算器,要求点击相关按键完成计算任务。老猿将计算器的所有按键分为三类,一类是操作数据和符号(包括数字、点、运算符、括号),按下是在显示界面直接显示对应字;第二类是...

osc_dmzfpa0c
2019/09/30
3
0
利用Python进行windows系统上的图像识别与点击(Mac OS系统也可以)

系统环境: 1、安装了python 2、安装了pyautogui模块 windows系统:无需安装依赖模块,在cmd中直接输入pip install pyautogui即可完成安装 Mac OS系统:需要先安装pyobjc模块,最后安装pyaut...

osc_1z8ghska
2019/08/14
7
0

没有更多内容

加载失败,请刷新页面

加载更多

使用Hadoop分析气象数据完整版(附带完整代码)

《分布式》布置了一道小作业,让我花了7天时间学习了Hadoop。。。现在终于可以正式地做这个作业了,记录一下。 使用Hadoop分析气象数据 1 获取数据 1.1 下载数据 1.2 数据格式 1.3 合并数据 ...

osc_igulbmxy
18分钟前
14
0
kubeadm安装部署kubernetes

使用kubeadm安装部署kubernetes集群 难点:kubeadm部署kubernetes集群 是把kubernetes的各个组件(kube-apiserver kube-controller-manager kube-scheduler kube-proxy etcd coredns)作为容器......

鸿FW
19分钟前
17
0
完整安装配置MAVEN环境

标题安装配置MAVEN环境 1. 下载MAVEN 网址:https://maven.apache.org/download.cgi 2. 配置环境变量 配置环境变量钱前你要安装和配置好了JAVA在继续 我下载的MAVEN 注意:文件的路径不要有...

osc_afjz4qba
19分钟前
22
0
Arcgis Online - Renderer篇

Arcgis Online - Renderer篇 1.Renderer SimpleRenderer 2.Symbol 3.案例 1.Renderer Renderer是一种地图要素渲染器,有多种类型的渲染器用于可视化数据,每种方法都有不同的用途,可以结合地...

osc_l7zl78wt
21分钟前
8
0
.NET IDE Rider公布2020.2路线图

跨平台 .NET IDE Rider 近日公布了 2020.2 的路线图,介绍了目前正在开发的一些特性,并表示其中一些可能在接下来的版本中出现。主要包括: Windows 上的 .NET Core 后端:Rider 2020.1 已在...

osc_zitca8hu
22分钟前
9
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部