简单版计算器

解题思路

一、计算器运算规则

优先级                    匹配格式

1. 小括号(最底层的)                    括号里没有括号

小括号里算式计算优先级:

2.幂运算            (正数)**(正数)、(正数)**(负数)     ---支持小数

3.乘除                (正数或负数)(*/)(正数或负数)         ---支持小数

4.加减                (正数或负数)(+-)(正数或负数)         ---支持小数

二、运算流程

1.search匹配第一个最底层的括号

2.通过match对象的groups方法获取括号里算式

3.对括号内的算式进行幂运算匹配

4.调用幂运算函数对匹配到的对象进行处理

5.用sub将结果替换括号内算式的匹配到的对象

6.重复3、4、5,直到没有匹配对象

7.对替换的算式进行乘除运算匹配

8.调用乘除运算函数对匹配到的对象进行处理

9.用sub将结果替换括号内算式的匹配到的对象

10.重复7、8、9直到没有匹配对象

11.对替换的算式进行加减运算匹配

12.调用加减运算函数对匹配到的对象进行处理

13.用sub将结果替换括号内算式的匹配到的对象

14.重复11、12、13直到没有匹配对象

15、重复上述步骤,直到没有括号

16.得到没有括号的算式后,只要再按照幂、乘除、加减步骤走

17.得到结果

流程图

  我还发现python在处理运算时,会自动帮我们处理正负号,所以在匹配时不用太多的去关心数字前的正负号

        

代码实现

#题目:求得字符串里‘1-2*((60-30+9*(9-2*5/3+7/3*99/4*2998+10*568/14))-(-4*3)/(16-3*2))‘计算式的结果

import re

#匹配规则
brackets = re.compile(‘\(([^()]+)\)‘)
powers = re.compile(‘(\d+\.?\d*)\*\*(\-?\d+\.?\d*)‘)
mul_div = re.compile(‘(\-?\d+\.?\d*)([*/])(\-?\d+\.?\d*)‘)
add_cut = re.compile(‘(\-?\d+\.?\d*)([+\-])(\-?\d+\.?\d*)‘)

def powers_calculate(match_obj):
    ‘‘‘
    处理幂运算
    :param match_obj: 需要处理的match对象
    :return:算式的结果
    ‘‘‘
    mat_grs = match_obj.groups()
    n1 = float(mat_grs[0])
    n2 = float(mat_grs[1])
    return n1**n2

def mul_div_calculate(match_obj):
    ‘‘‘
    处理乘除运算
    :param match_obj: 需要处理的match对象
    :return: 算式的结果
    ‘‘‘
    mat_grs = match_obj.groups()
    n1 = float(mat_grs[0])
    n2 = float(mat_grs[2])
    if mat_grs[1] == ‘*‘:
        return n1*n2
    else:
        return n1/n2

def add_cut_calculate(match_obj):
    ‘‘‘
    处理加减运算
    :param match_obj: 需要处理的match对象
    :return: 算式的结果
    ‘‘‘
    mat_grs = match_obj.groups()
    n1 = float(mat_grs[0])
    n2 = float(mat_grs[2])
    if mat_grs[1] == ‘+‘:
        return n1+n2
    else:
        return n1-n2

#数据源
data_sour = ‘1-2*((60-30+9*(9-2*5/3+7/3*99/4*2998+10*568/14))-(-4*3)/(16-3*2))‘

# data_sour = input(‘请输入你要计算的算式:‘)
#==================================================================================

#匹配最底层的括号
brackets_match = brackets.search(data_sour)

#对匹配到的括号进行处理
while True:
    if brackets_match:                  #判断匹配成功与否
        print(brackets_match.group())   #(9-2*5/3+7/3*99/4*2998+10*568/14)
        mat_groups1 = brackets_match.groups()  #得到去括号的组的值,不过此时这里是元组
        print(mat_groups1)              #(‘9-2*5/3+7/3*99/4*2998+10*568/14‘,)

        #处理幂运算
        text = mat_groups1[0]      #得到最底层括号里的算式字符串
        powers_match = powers.search(text)  #匹配幂运算
        while True:
            if powers_match:                #判断匹配成功与否
                print(powers_match.group())
                ret1 = powers_calculate(powers_match) #调用幂运算函数
                print(ret1)
                text = re.sub(powers,str(ret1),text,1)  #把得到的幂运算结果替换匹配到的字符串
                powers_match = powers.search(text)      #对替换的字符串再次进行幂运算匹配
            else:
                break                        #匹配失败,就退出匹配幂运算的循环

        #处理乘除运算
        mul_div_match = mul_div.search(text)  #对处理幂运算后的字符串进行乘除运算匹配
        while True:
            if mul_div_match:                 #判断匹配成功与否
                print(mul_div_match.group())
                ret2 = mul_div_calculate(mul_div_match)  #调用乘除运算函数
                print(ret2)
                text = re.sub(mul_div,str(ret2),text,1)  #把得到的乘除运算结果替换匹配的字符串
                print(text)
                mul_div_match = mul_div.search(text)     #对处理后的字符串再进行乘除运算匹配
            else:
                break   #匹配失败,就退出匹配乘除运算的循环

        #处理加减运算
        add_cut_match = add_cut.search(text)    #对处理乘除后的字符串进行加减运算匹配
        while True:
            if add_cut_match:                   #判断匹配成功与否
                print(add_cut_match.group())
                ret3 = add_cut_calculate(add_cut_match)  #调用加减运算函数
                text = re.sub(add_cut,str(ret3),text,1)  #用得到的加减运算结果替换匹配的字符串
                print(text)
                add_cut_match = add_cut.search(text)  #对处理后的字符串再进行加减运算匹配
            else:
                break      #匹配失败,退出匹配加减运算的循环

        data_sour = re.sub(brackets,text,data_sour,1)  #把括号里的计算结果替换匹配的括号
        brackets_match = brackets.search(data_sour)   #再次对处理后字符串进行括号的匹配

    else:
        break     #匹配不到括号,就退出匹配括号的循环

#对处理括号完后的算式进行最后的运算
#幂
powers_match = powers.search(data_sour)
while True:
    if powers_match:
        ret1 = powers_calculate(powers_match)
        data_sour = re.sub(powers,str(ret1),data_sour,1)
        powers_match = powers.search(data_sour)
    else:
        break

#乘除
mul_div_match = mul_div.search(data_sour)
while True:
    if mul_div_match:
        ret1 = mul_div_calculate(mul_div_match)
        data_sour = re.sub(mul_div, str(ret1), data_sour, 1)
        mul_div_match = mul_div.search(data_sour)
    else:
        break

#加减
add_cut_match = add_cut.search(data_sour)
while True:
    if add_cut_match:
        ret1 = add_cut_calculate(add_cut_match)
        data_sour = re.sub(add_cut, str(ret1), data_sour, 1)
        add_cut_match = add_cut.search(data_sour)
    else:
        break

print(‘最后结果为:‘,data_sour)

#验证结果
data_sour = ‘1-2*((60-30+9*(9-2*5/3+7/3*99/4*2998+10*568/14))-(-4*3)/(16-3*2))‘
jieguo = eval(data_sour)
print(‘验证结果:‘,jieguo)
时间: 2024-08-15 12:12:24

简单版计算器的相关文章

GTK简单版计算器

接下来我们做一个简单版的计算器. 1)获取按钮上的内容. 2)如果获取的内容是" c ",则代表进行退格操作,相当于删去最后一个字符. 3)如果获取的内容不是" c ",则把每一次获取的内容连接起来,如: 第一次按了 " 1 ", 第二次按了 " + ", 第三次按了 " 1 ", 连起来则变为 "1+1". 4)如果获取的内容是" = ",则需要相应的运算.先把连起

超级简单版多态计算器

个人笔记学习黑马四期 一.编写一个操作父类 using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace 多态计算器 { /// <summary> /// 计算父类 /// </summary> class Operation { public int NumA { get; set; } p

Swift之旅:1.概述-用Swift实现一个简单的计算器

学习所用到的资源: 斯坦福大学公开课:iOS 8开发 网易空开课地址链接:斯坦福大学公开课:IOS8开发 github上字幕链接:字幕 百度网盘资源下载链接:百度网盘 1.详解IOS编程的四个层 ①cocoa touch层 这是我们最长用到的层,里面最长用到的当然是最基础的控件 ②媒体层(Media) ③核心服务层 ④核心操作系统层 2.新建一个Swift的IOS工程 ①打开Xcode,按照图示新建一个工程 ②选择Application 然后 单击Sigle View Application.

从0到1:使用Caliburn.Micro(WPF和MVVM)开发简单的计算器

从0到1:使用Caliburn.Micro(WPF和MVVM)开发简单的计算器 之前时间一直在使用Caliburn.Micro这种应用了MVVM模式的WPF框架做开发,是时候总结一下了. Caliburn.Micro(Caliburn.Micro框架概述 - https://blog.csdn.net/lzuacm/article/details/78886436) 是一个轻量级的WPF框架,简化了WPF中的不少用法,推荐做WPF开发时优先使用. 真正快速而熟练地掌握一门技术就可以尝试着用最快的

JS实现一个简单的计算器

使用JS完成一个简单的计算器功能.实现2个输入框中输入整数后,点击第三个输入框能给出2个整数的加减乘除.效果如上: 第一步: 创建构建运算函数count(). 第二步: 获取两个输入框中的值和获取选择框的值. 提示:document.getElementById( id名 ).value 获取或设置 id名的值. 第三步: 获取通过下拉框来选择的值来改变加减乘除的运算法则. 提示:使用switch判断运算法则. 第四步:  通过 = 按钮来调用创建的函数,得到结果. 注意: 使用parseInt

分享一个近期写的简单版的网页采集器

分享一个近期写的简单版的网页采集器 功能特点: 1.可通过配置,保存采集规则. 2.可通过采集规则,进行数据采集. 3.可分页,分关键字,进行采集. 4.可保存数据至数据库,文本中. ........... 功能还比较简单,喜欢深入的可以继续深入下去,暂时还没有登录的功能,因为登录功能涉及到的范围比较广,待日后慢慢研究后再开发. 我先上个图让大家一睹为快吧: 首先看看页面,我们要采集这个网站的文章 接下来,首先是查找分页,获得分页里面的文章链接,接着查找内容页需要采集的字段,生成规则,进行采集.

留念 C语言第一课简单的计算器制作

学C语言这么久了.  /* 留念 C语言第一课简单的计算器制作 */ #include<stdio.h>  #include<stdlib.h> #include<conio.h>void displayMenu();void add();void sub();void multiply();void divide();void yushu();void jiecheng();void leijia();void jiechengleijia();int main(in

Java实现简单版SVM

最近的图像分类工作要用到latent svm,为了更加深入了解svm,自己动手实现一个简单版的. 之所以说是简单版,因为没有用到拉格朗日,对偶,核函数等等.而是用最简单的梯度下降法求解.其中的数学原理我参考了http://blog.csdn.net/lifeitengup/article/details/10951655,文中是用matlab实现的svm. 源代码和数据集下载:https://github.com/linger2012/simpleSvm 其中数据集来自于libsvm,我找了其中

MFC抓取网页代码简单版。

最近又在网上找了一些有关MFC抓取网页代码的文章看,发现有个比较简单的代码,和大家分享下. CInternetSession session(NULL, 0); CHttpFile* htmlFile = NULL; CString strLine, strHtml; CString url = _T("http://www.tqyb.com.cn/data/gzWeather/gz_weatherForecastInDays.js?"); TCHAR sRecv[1024]; UIN