博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
利用正则制作计算器
阅读量:4341 次
发布时间:2019-06-07

本文共 4998 字,大约阅读时间需要 16 分钟。

核心思想:1.先考虑没有括号的式子如何进行运算,然后考虑正则匹配有括号的式子,通过逐步替换

利用正则计算:1 - 2 * ( (60-30 +(-40/5) * 20) - (-4*3)/ (16-3*2) )

# 方案1

#!/usr/bin/env python    # -*- coding:utf-8 -*-# author: Learning       time:2018/4/30import re# 定义一个乘除运算函数,最终返回一个运算结果def mul_div(cal):    if '*' in cal:        x, y = cal.split('*')        return float(x) * float(y)    if '/' in cal:        x, y = cal.split('/')        return float(x) / float(y)    # 定义一个处理加减符号的函数,这步是由于乘除运算完可能为负导致的def proce_symbol(cal):    cal = cal.replace('++','+')    cal = cal.replace('+-', '-')    cal = cal.replace('--', '+')    cal = cal.replace('-+', '-')    return cal# 定义一个对内层没有括号的公式进行运算的函数,最终返回一个结果def inner(content):    """    这步对内层的乘除进行循环处理,直到里面没有了乘除运算,全部替换成了结果    :param content:    :type content:    :return: 一个不带括号的运算式的结果    :rtype:    """    # 浮点型匹配整数和浮点数啊哥,不是整数匹配浮点数    # 最后变成这样1-2*-128.8,要注意这里的正则匹配    con = re.search(r'\d+\.?\d*[*/]\-?\d+\.?\d*', content)    while con:  # 如果当中有乘除号        con = con.group()        temp = mul_div(con)  # 得到结果        content = content.replace(con,str(temp))  # 对内层运算式进行替换        content = proce_symbol(content)        #替换计算式中的乘除运算,直到替换完,对于冲突的+-号也进行替换        return inner(content)   # 通过循环一直运算式中的乘除运算计算完    else:   # 如果没有乘除号        # 对加减进行运算处理,把他们整到列表里面,挨个进行处理计算        lis = re.findall(r'[+-]?\d+\.?\d*', content)        if len(lis)>0:            total_num = 0            for i in lis:                total_num += float(i)            return total_num        else:            return lis[0]# 匹配最内层的括号def pars(cal):    """    定义一个计算最内层运算的函数    :param cal:    :type cal:    :return:最能层运算    :rtype:    """    par = re.search('\(([^()]*)\)', cal)    while par:   # 如果当中有括号        content = par.group()   # (-40/5)        temp = inner(content.strip('()'))  # 去括号,并处理结果-8        cal = cal.replace(content,str(temp))        return pars(cal)    # 判断里面的运算符,可以有加减乘除    else:        ret = inner(cal) # 如果没有括号        return reta = input('计算式:').strip()# 去除空格处理,得到1-2*((60-30+(-40/5)*20)-(-4*3)/(16-3*2))a = re.sub('\s','', a)print(pars(a))

 方案2:

import redef cal(exp):    if '*' in exp:        a,b = exp.split('*')        return str(float(a) * float(b))    elif '/' in exp:        a, b = exp.split('/')        return str(float(a) / float(b))def format(exp):    exp = exp.replace('++',"+")    exp = exp.replace('-+',"-")    exp = exp.replace('+-',"-")    exp = exp.replace('--',"+")    return expdef dealwith(no_bracket_exp):    # 匹配乘除法    while True:        mul_div = re.search('\d+(\.?\d+)?[*/]-?\d+(\.?\d+)?', no_bracket_exp)        if mul_div:            exp = mul_div.group()            result = cal(exp)            no_bracket_exp = no_bracket_exp.replace(exp, result, 1)  # (-8)        else:break    no_bracket_exp = format(no_bracket_exp)    # 计算加减法    lst = re.findall(r'[-+]?\d+(?:\.\d+)?', no_bracket_exp)    res = str(sum([float(i) for i in lst]))    return res   # 返回一个计算完毕的字符串数据类型的 数字def remove_bracket(s):    s = s.replace(' ', '')     # 去掉空格    while True:        ret = re.search(r'\([^()]+\)', s)   # 匹配最内层的括号        if ret:      # 能匹配到括号 就先处理括号内的加减乘除            no_bracket_exp = ret.group()    # 拿到括号中的表达式            ret = dealwith(no_bracket_exp)  # 把括号中的表达式交给的dealwith            s = s.replace(no_bracket_exp, ret, 1)        else:       # 不能匹配到括号 就字节处理加减乘除            ret = dealwith(s)  # 把表达式交给的dealwith            return rets = '1 - 2 * ( (60-30 +(-40/5) * (9-2*5/3 + 7 /3*99/4*2998 +10 * 568/14 )) - (-4*3)/ (16-3*2) )'print(remove_bracket(s))

 和方案二一样:

a = '1 - 2 * ( (60-30 +(-40/5) * 20) - (-4*3)/ (16-3*2) )'import renew_a = re.sub(' ','',a)  # 去括号处理def proce_symbol(cal):  # 去重复加减号    if '++' in cal:cal = cal.replace('++','+')    if '+-' in cal:cal = cal.replace('+-', '-')    if '--' in cal:cal = cal.replace('--', '+')    if '-+' in cal:cal = cal.replace('-+', '-')    return caldef mul_div(famula):    if '*' in famula:        num1, num2 = famula.split('*')        total = str(float(num1) * float(num2))        return total    if '/' in famula:        num1, num2 = famula.split('/')        total = str(float(num1) / float(num2))        return totaldef total(famula):    while True:        if '*' or '/' in famula:            num = re.search(r'\d+(\.?\d+)?[*/]\-?\d+(\.?\d+)?',famula)            if num:                num = num.group()                nums = mul_div(num)                famula = famula.replace(num, nums, 1)                famula = proce_symbol(famula)           # 如果算式中剩下加减运算            else:                lis = re.findall(r'[-]?\d+(?:\.?\d+)?',famula)                sums = sum([float(i) for i in lis])                return sumsdef bras(famu):    while True:        bra = re.search('\([^()]+\)',famu)  # 获取括号内的内容        if bra:            bra = bra.group()            ret = total(bra)            famu = famu.replace(bra,str(ret),1)            s = proce_symbol(famu)            return bras(s)        else:            s = proce_symbol(famu)            ret = total(s)            return retprint(bras(new_a))  

  

  

 

转载于:https://www.cnblogs.com/LearningOnline/articles/9008883.html

你可能感兴趣的文章
小D课堂 - 零基础入门SpringBoot2.X到实战_第9节 SpringBoot2.x整合Redis实战_40、Redis工具类封装讲解和实战...
查看>>
小D课堂 - 零基础入门SpringBoot2.X到实战_第9节 SpringBoot2.x整合Redis实战_37、分布式缓存Redis介绍...
查看>>
小D课堂 - 零基础入门SpringBoot2.X到实战_第10节 SpringBoot整合定时任务和异步任务处理_42、SpringBoot常用定时任务配置实战...
查看>>
小D课堂 - 零基础入门SpringBoot2.X到实战_第9节 SpringBoot2.x整合Redis实战_39、SpringBoot2.x整合redis实战讲解...
查看>>
小D课堂 - 零基础入门SpringBoot2.X到实战_第14节 高级篇幅之SpringBoot多环境配置_59、SpringBoot多环境配置介绍和项目实战...
查看>>
小D课堂 - 零基础入门SpringBoot2.X到实战_第10节 SpringBoot整合定时任务和异步任务处理_41、SpringBoot定时任务schedule讲解...
查看>>
小D课堂 - 零基础入门SpringBoot2.X到实战_第10节 SpringBoot整合定时任务和异步任务处理_43、SpringBoot2.x异步任务实战(核心知识)...
查看>>
小D课堂 - 新版本微服务springcloud+Docker教程_1_01课程简介
查看>>
小D课堂 - 零基础入门SpringBoot2.X到实战_第11节 Logback日志框架介绍和SpringBoot整合实战_45、SpringBoot2.x日志讲解和Logback配置实战...
查看>>
小D课堂 - 新版本微服务springcloud+Docker教程_3-05 服务注册和发现Eureka Server搭建实战...
查看>>
小D课堂 - 新版本微服务springcloud+Docker教程_4-05 微服务调用方式之feign 实战 订单调用商品服务...
查看>>
UI基础--烟花动画
查看>>
Android dex分包方案
查看>>
ThreadLocal为什么要用WeakReference
查看>>
删除本地文件
查看>>
FOC实现概述
查看>>
base64编码的图片字节流存入html页面中的显示
查看>>
这个大学时代的博客不在维护了,请移步到我的新博客
查看>>
GUI学习之二十一——QSlider、QScroll、QDial学习总结
查看>>
gethostbyname与sockaddr_in的完美组合
查看>>