python实现计算器

版权声明:本文为博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/u011881908/article/details/50939973

用python写了个计算器。可以实现对“+”,“-”,“*”,“/”以及括号的混合表达式的计算。
一开始在解析表达式时使用了两个递归,最后报运行时错误,提示递归深度不够,使用sys设置了下递归深度,还是不行,一旦设置太大就会出现内存错误,可能本人的机器太low了。后来把其中一个递归改成了循环,最终可以正常工作。

# coding:utf-8
# Author:李彪
# date:2016-03-20

#计算包含+、-、*、/以及多重括号的数字表达式:'-1-(2+(10-2*3)/(20-30/5))+(100-(4-300/6)-5*9/4+5)'
#没有对表达式中运算数进行非数字类型的判断---后期可添加

import re
import sys
import argparse

#设置递归深度
sys.setrecursionlimit(5000)
#这个类里面使用了递归,运行会提示递归深度不够,也许我的机器太low-----有兴趣的也许可以尝试下
class MyMaths():
    def __init__(self):
       pass

    #计算表达式的值,并返回
    def operatorParse(self,express):
        # operators = {'+':self.addition,'-':self.subtraction,'*':self.multiplication,'/':self.division}
        express = express.group()
        **#这里的判定比较简单,么有做太多的考虑,肯定存在一定的问题**
        if '+' in express:
            return self.addition(express)

        if '-' in express:
            return self.subtraction(express)

        if '*' in express:
            return self.multiplication(express)

        if '/' in express:
            return self.division(express)

    #加法运算
    def addition(self,express):
        first_data,second_data = express.split('+')
        return str(float(first_data)+float(second_data))

    #减法运算
    def subtraction(self,express):
        #判定第一个运算数为负数的情况
        if express.startswith('-'):
            first_data,second_data = express[1:].split('-',1)#减法运算时,仅使用‘-’split一次
            first_data = '-' + first_data
        else:
            first_data,second_data = express.split('-',1)
        return str(float(first_data)-float(second_data))

    #乘法运算
    def multiplication(self,express):
        first_data,second_data = express.split('*')
        return str(float(first_data)*float(second_data))

    #除法运算
    def division(self,express):
        first_data,second_data = express.split('/')
        return str(float(first_data)/float(second_data))

    **#使用了递归,会出现运行时错误,提示递归深度超过**
    def operator_priority(self,express):
        pattern_1 = re.compile('(\-?\d+\.?\d*(\*|\/)+\-?\d+\.?\d*)')
        pattern_2 = re.compile('(\-?\d+\.?\d*(\+|\-)+\-?\d+\.?\d*)')
        if re.search(pattern_1,express):
            express = re.sub(pattern_1,self.operatorParse,express)
            return self.operator_priority(express)
        elif re.search(pattern_2,express):
            express = re.sub(pattern_2,self.operatorParse,express)
            return self.operator_priority(express)
        else:
            return express
#计算表达式的值,并返回,使用内部方法
def operatorParse(express):
    # operators = {'+':self.addition,'-':self.subtraction,'*':self.multiplication,'/':self.division}

    #加法运算
    def addition(express):
        first_data,second_data = express.split('+')
        return str(float(first_data)+float(second_data))

    #减法运算
    def subtraction(express):
        #判定第一个运算数为负数的情况
        if express.startswith('-'):
            #减法运算时,仅使用‘-’split一次
            first_data,second_data = express[1:].split('-',1)
            first_data = '-' + first_data
        else:
            first_data,second_data = express.split('-',1)
        return str(float(first_data)-float(second_data))

    #乘法运算
    def multiplication(express):
        first_data,second_data = express.split('*')
        return str(float(first_data)*float(second_data))

    #除法运算
    def division(express):
        first_data,second_data = express.split('/')
        return str(float(first_data)/float(second_data))

    express = express.group()
    **#这里的判定比较简单,么有做太多的考虑,肯定存在一定的问题**
    if '+' in express:
        return addition(express)

    if '-' in express:
        return subtraction(express)

    if '*' in express:
        return multiplication(express)

    if '/' in express:
        return division(express)

#express表达式中包含‘+’,‘-’,‘*’,‘/’运算符,operator_priority按照运算优先级进行运算
def operator_priority(express):
    #首先通过循环首先来判断express中是否包含‘*’或者‘/’的表达式
    pattern = re.compile('(\d+\.?\d*(\*|\/)+\-?\d+\.?\d*)')
    while re.search(pattern,express):#re.search('(\*|\/)',express):
        #如果express中包含乘法或者除法表达式,那么使用re.sub方法将符合正则条件的表达式提取并传给operatorParse
        #用operatorParse返回值替换提取出来的表达式
        #express指向完成替换操作的新的表达式,并再次循环判断
        # print re.search(pattern,express).group()
        express = re.sub(pattern,operatorParse,express)

    #通过循环首先来判断express中是否包含‘+’或者‘-’的表达式
    pattern = re.compile('(\-?\d+\.?\d*(\+|\-)+\d+\.?\d*)')
    while re.search(pattern,express):#re.search('(\+|\-)',express):
        #如果express中包含乘法或者除法表达式,那么使用re.sub方法将符合正则条件的表达式提取并传给operatorParse
        #用operatorParse返回值替换提取出来的表达式
        #express指向完成替换操作的新的表达式,并再次循环判断
        express = re.sub(pattern,operatorParse,express)
    return express


#以递归的方式从最里层将表达式中成对的带括号的表达式提取,作为参数传递给operator_priority方法
def parseBracket(srcStr):
    # my_maths = MyMaths()
    if '(' in srcStr or ')' in srcStr:
        #查找第一个出现的‘)’的位置
        first_Rbracket_pos = srcStr.find(')')
        match_lbrocket_pos = None
        for i in xrange(first_Rbracket_pos):
            #根据第一个‘)’的下标往前搜索,直到找到最近的‘(’
            if srcStr[first_Rbracket_pos - i] == '(':
                match_lbrocket_pos = first_Rbracket_pos - i
                break
            else:
                continue
        #根据找到的‘(’和‘)’下标,截取带括号的表达式
        sub_Expression = srcStr[match_lbrocket_pos:first_Rbracket_pos+1]
        # print sub_Expression
        #调用my_maths.operator_priority,该方法根据操作符优先级计算表达式的值并返回
        retStr = operator_priority(sub_Expression.lstrip('(').rstrip(')'))
        # print retStr
        #用返回的值替换原表达式中提取的子表达式,生成新的表达式
        newExpre = srcStr.replace(sub_Expression,retStr)
        # print newExpre
        #递归调用
        return parseBracket(newExpre)
    else:
        #表达式中不再包含‘()’,此时直接将表达式传递到operator_priority进行运算,得到最终结果
        retStr = operator_priority(srcStr)
        return retStr

if __name__ == '__main__':
    s = "-200-(1-(2+(10-2*3/2)/(20-30/5))+(100-(4-300/6)-5*9/4+5))"
    print s + " = " + parseBracket(s)

程序测试运行,结果如下:
-200-(1-(2+(10-2*3/2)/(20-30/5))+(100-(4-300/6)-5*9/4+5)) = -338.25

展开阅读全文

没有更多推荐了,返回首页