一个四则运算器的实现

        这里要实现一个计算器,输入一个算术表达式,输出计算结果,支持加减乘除四则运算,操作数可以是负数,可以使用括号。

         首先我们需要搞清楚什么样的表达式是一个合法的算术表达式,下面给出算术表达式的文法,

         E -> E + T | E - T | T

         T -> T * F | T / F | F

         F -> -num | num | (E)

         由文法能生成的表达式是合法的算术表达式,不能由文法生成的表达式不是合法的算术表达式。

         由文法可知,数值是合法的算术表达式,算术表达式通过+ - * /连接得到的还是算术表达式,算术表达式被()括起来还是算术表达式。

        由文法可知运算数和运算符是交替出现的,(E)作为一个整体去看,它是一个运算数,如果我们把它代换为numE,括号被消除之后,整个表达式要么是一个单一的运算数,要么是运算数和运算符交替出现的一个串(串的首尾都是运算数),因此,当我们从左至右去解释执行算术表达式的时候,就有一个预期,一开始我们预期得到一个运算数(可以是括号括起来的表达式),接下来预期得到一个运算符,再接下来预期得到一个运算数,依次交替。当我们得到了两个运算数和一个运算符的时候,是不是立即展开计算?不一定,举例来说,1+2*3,我们不能计算1+2,而是要先计算2*3,如果是1*2+3,就能立即计算1*2了,因为运算具有优先级的缘故,当前运算符能不能被立即执行计算要看下一个运算符的运算优先级,如果当前运算符优先级更高,则执行计算,否则,先计算下一个运算符后再执行当前运算符,这是我们解释执行算术表达式的逻辑基础,下面看源码实现。

class Calc(object):
    def __call__(self, exp):
        self.exp = exp
        self.explen = len(exp)
        self.pos = 0
        return self._calc()

    def consumeblanks(self):
        exp = self.exp
        explen = len(exp)
        pos = self.pos
        while pos < explen:
            if exp[pos] in [' ', '\t', '\v', '\n']:
                pos += 1
            else:
                break
        if pos != self.pos:
           self.pos = pos

    def get_number(self):
        exp = self.exp
        self.consumeblanks()
        if exp[self.pos] == '(':
            self.pos += 1
            return self._calc(True)
        else:
            width = 0
            if exp[self.pos] in ('+', '-'):
                width = 1
            for i in range(self.pos + width, len(self.exp)):
                if exp[i] in ('+', '-', '*', '/', ')'):
                    break
                width += 1
            num = float(exp[self.pos: self.pos + width])
            self.pos += width
            return num

    def get_operator(self):
        self.consumeblanks()
        if self.pos == len(self.exp):
            return None

        op = self.exp[self.pos]
        if op not in ('+', '-', '*', '/', ')'):
            raise ValueError("operator '%s' not supported" % op)
        self.pos += 1
        
        return op

    def _calc(self, issubexp = False):
        left = self.get_number()
        op = self.get_operator()
        if issubexp:
            if op == ')':
                return left
        else:
            if op == None:
                return left
            if op == ')':
                raise ValueError("calc expression %s is invalid!" % self.exp)
        if op == '+':
            result = self.add(left)
        elif op == '-':
            result = self.dec(left)
        elif op == '*':
            result = self.mul(left)
        elif op == '/':
            result = self.div(left)
        
        if issubexp:
            if self.exp[self.pos - 1] != ')':
                raise ValueError("calc expression %s is invalid!" % self.exp)
        else:
            if self.exp[self.pos - 1] == ')':
                raise ValueError("calc expression %s is invalid!" % self.exp)

        return result

    def add(self, left):
        right = self.get_number()
        op2 = self.get_operator()
        if op2 == ')' or op2 == None:
            print("%f + %f = %f" % (left, right, left + right))
            return left + right
        if op2 == '+':
            print("%f + %f = %f" % (left, right, left + right))
            return self.add(left + right)
        elif op2 == '-':
            print("%f + %f = %f" % (left, right, left + right))
            return self.dec(left + right)
        elif op2 == '*':
            right = self.mul(right)
            print("%f + %f = %f" % (left, right, left + right))
            return left + right
        elif op2 == '/':
            right = self.div(right)
            print("%f + %f = %f" % (left, right, left + right))
            return left + right

    def dec(self, left):
        right = self.get_number()
        op2 = self.get_operator()
        if op2 == ')' or op2 == None:
            print("%f - %f = %f" % (left, right, left - right))
            return left - right
        if op2 == '+':
            print("%f - %f = %f" % (left, right, left - right))
            return self.add(left - right)
        elif op2 == '-':
            print("%f - %f = %f" % (left, right, left - right))
            return self.dec(left - right)
        elif op2 == '*':
            right = self.mul(right)
            print("%f - %f = %f" % (left, right, left - right))
            return left - right
        elif op2 == '/':
            right = self.div(right)
            print("%f - %f = %f" % (left, right, left - right))
            return left - right
        

    def mul(self, left):
        right = self.get_number()
        op2 = self.get_operator()
        if op2 == ')' or op2 == None:
            print("%f * %f = %f" % (left, right, left * right))
            return left * right
        if op2 == '+':
            print("%f * %f = %f" % (left, right, left * right))
            return self.add(left * right)
        elif op2 == '-':
            print("%f * %f = %f" % (left, right, left * right))
            return self.dec(left * right)
        elif op2 == '*':
            print("%f * %f = %f" % (left, right, left * right))
            return self.mul(left * right)
        elif op2 == '/':
            print("%f * %f = %f" % (left, right, left * right))
            return self.div(left * right)

    def div(self, left):
        right = self.get_number()
        op2 = self.get_operator()
        if op2 == ')' or op2 == None:
            print("%f / %f = %f" % (left, right, left / right))
            return left / right
        if op2 == '+':
            print("%f / %f = %f" % (left, right, left / right))
            return self.add(left / right)
        elif op2 == '-':
            print("%f / %f = %f" % (left, right, left / right))
            return self.dec(left / right)
        elif op2 == '*':
            print("%f / %f = %f" % (left, right, left / right))
            return self.mul(left / right)
        elif op2 == '/':
            print("%f / %f = %f" % (left, right, left / right))
            return self.div(left /right)

_c = Calc()
print(_c("1"))
print(_c("(1)"))
print(_c("(+1+2)*-1+3/3"))


  • 13
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

__空无一人__

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值