Stubborn 发表于 2020-5-30 13:55:57

编写一个函数parse,实现计算器功能

本帖最后由 Stubborn 于 2020-5-30 16:27 编辑

编写一个函数parse,实现计算器功能,仅支持   + - * / () ,整数。 如果表达式不正确,引发一个异常(不要使用内建函数直接返回答案,例如eval())
实例

parse('1+2')
>>>3
parse('1+2*3')
>>>7
parse('1+2*(1+3)')
>>>9
parse('1+9/3')
>>>4



**** Hidden Message *****

xiaosi4081 发表于 2020-5-30 13:55:58

本帖最后由 xiaosi4081 于 2020-6-1 18:04 编辑

import re
class suan:
    def calculate(self,n1, n2, operator):

      '''
      :param n1: float
      :param n2: float
      :param operator: + - * /
      :return: float
      '''
      result = 0
      if operator == "+":
            result = n1 + n2
      if operator == "-":
            result = n1 - n2
      if operator == "*":
            result = n1 * n2
      if operator == "/":
            result = n1 / n2
      return result


    # 判断是否是运算符,如果是返回True
    def is_operator(self,e):
      '''
      :param e: str
      :return: bool
      '''
      opers = ['+', '-', '*', '/', '(', ')']
      return True if e in opers else False


    # 将算式处理成列表,解决横杠是负数还是减号的问题
    def formula_format(self,formula):
      # 去掉算式中的空格
      formula = re.sub(' ', '', formula)
      # 以 '横杠数字' 分割, 其中正则表达式:(\-\d+\.?\d*) 括号内:
      # \- 表示匹配横杠开头; \d+ 表示匹配数字1次或多次;\.?表示匹配小数点0次或1次;\d*表示匹配数字1次或多次。
      formula_list =

      # 最终的算式列表
      final_formula = []
      for item in formula_list:
            # 第一个是以横杠开头的数字(包括小数)final_formula。即第一个是负数,横杠就不是减号
            if len(final_formula) == 0 and re.search('^\-\d+\.?\d*', item):
                final_formula.append(item)
                continue

            if len(final_formula) > 0:
                # 如果final_formal最后一个元素是运算符['+', '-', '*', '/', '('], 则横杠数字不是负数
                if re.search('[\+\-\*\/\(], final_formula[-1]'):
                  final_formula.append(item)
                  continue
            # 按照运算符分割开
            item_split = )', item) if i]
            final_formula += item_split
      return final_formula


    def decision(self,tail_op, now_op):
      '''
      :param tail_op: 运算符栈的最后一个运算符
      :param now_op: 从算式列表取出的当前运算符
      :return: 1 代表弹栈运算,0 代表弹运算符栈最后一个元素, -1 表示入栈
      '''
      # 定义4种运算符级别
      rate1 = ['+', '-']
      rate2 = ['*', '/']
      rate3 = ['(']
      rate4 = [')']

      if tail_op in rate1:
            if now_op in rate2 or now_op in rate3:
                # 说明连续两个运算优先级不一样,需要入栈
                return -1
            else:
                return 1

      elif tail_op in rate2:
            if now_op in rate3:
                return -1
            else:
                return 1

      elif tail_op in rate3:
            if now_op in rate4:
                return 0   # ( 遇上 ) 需要弹出 (,丢掉 )
            else:
                return -1# 只要栈顶元素为(,当前元素不是)都应入栈。
      else:
            return -1


    def final_calc(self,formula_list):
      num_stack = []       # 数字栈
      op_stack = []      # 运算符栈
      for e in formula_list:
            operator = self.is_operator(e)
            if not operator:
                # 压入数字栈
                # 字符串转换为符点数
                num_stack.append(float(e))
            else:
                # 如果是运算符
                while True:
                  # 如果运算符栈等于0无条件入栈
                  if len(op_stack) == 0:
                        op_stack.append(e)
                        break

                  # decision 函数做决策
                  tag = decision(op_stack[-1], e)
                  if tag == -1:
                        # 如果是-1压入运算符栈进入下一次循环
                        op_stack.append(e)
                        break
                  elif tag == 0:
                        # 如果是0弹出运算符栈内最后一个(, 丢掉当前),进入下一次循环
                        op_stack.pop()
                        break
                  elif tag == 1:
                        # 如果是1弹出运算符栈内最后两个元素,弹出数字栈最后两位元素。
                        op = op_stack.pop()
                        num2 = num_stack.pop()
                        num1 = num_stack.pop()
                        # 执行计算
                        # 计算之后压入数字栈
                        num_stack.append(self.calculate(num1, num2, op))
      # 处理大循环结束后 数字栈和运算符栈中可能还有元素 的情况
      while len(op_stack) != 0:
            op = op_stack.pop()
            num2 = num_stack.pop()
            num1 = num_stack.pop()
            num_stack.append(self.calculate(num1, num2, op))

      return num_stack, op_stack

    def pause(self,formula):
      formula_list = self.formula_format(formula)
      result, _ = self.final_calc(formula_list)
      print(result)
try:
    p = suan()
    formula = input()
    p.pause(formula)
except:
    print(formula)

永恒的蓝色梦想 发表于 2020-5-30 14:49:17

给出一个作弊答案:parse=eval

liaoyiqin 发表于 2020-5-30 15:31:16

这不可能实现的,函数的参数必须指定,两个数且不是字符串用逗号隔开才行

liaoyiqin 发表于 2020-5-30 15:34:44

这样我能帮你实现

liaoyiqin 发表于 2020-5-30 15:39:05

这样我能帮你实现

Cool_Breeze 发表于 2020-5-30 15:42:36

给你链接给你百度一下百度一下https://www.cnblogs.com/zingp/p/8666214.html

liaoyiqin 发表于 2020-5-30 15:55:27

Cool_Breeze 发表于 2020-5-30 15:42
给你链接给你百度一下百度一下https://www.cnblogs.com/zingp/p/8666214.html

我是过运行你给的文件,但是没有输入

Cool_Breeze 发表于 2020-5-30 15:57:23

liaoyiqin 发表于 2020-5-30 15:55
我是过运行你给的文件,但是没有输入

这个不是我的,大佬写的!

Stubborn 发表于 2020-5-30 16:00:56

liaoyiqin 发表于 2020-5-30 15:31
这不可能实现的,函数的参数必须指定,两个数且不是字符串用逗号隔开才行

需要我贴代码出来吗,功能是可以实现的

liaoyiqin 发表于 2020-5-30 16:01:37

Cool_Breeze 发表于 2020-5-30 15:57
这个不是我的,大佬写的!

嗯嗯,这个计算器的操作数是不能随意选择的

liaoyiqin 发表于 2020-5-30 16:09:15

Stubborn 发表于 2020-5-30 16:00
需要我贴代码出来吗,功能是可以实现的

好的

Stubborn 发表于 2020-5-30 16:29:22

liaoyiqin 发表于 2020-5-30 16:09
好的

在隐藏里面了{:10_333:}

宋恺 发表于 2020-5-30 16:50:19

干嘛隐藏{:10_277:}

hrp 发表于 2020-5-30 16:57:23

参观大佬的代码

Twilight6 发表于 2020-5-30 17:02:32

Stubborn 发表于 2020-5-30 16:29
在隐藏里面了

这样就没意思了呀,晚上我还想写写看呢,虽然很大概率写不出来{:10_297:}

永恒的蓝色梦想 发表于 2020-5-30 17:08:24

liaoyiqin 发表于 2020-5-30 15:31
这不可能实现的,函数的参数必须指定,两个数且不是字符串用逗号隔开才行

不要自己不会就说不可能。

Stubborn 发表于 2020-5-30 17:46:01

Twilight6 发表于 2020-5-30 17:02
这样就没意思了呀,晚上我还想写写看呢,虽然很大概率写不出来

不要看答案吗,写起来才有意思{:10_282:}

java2python 发表于 2020-5-30 20:30:44

答案

叶师傅 发表于 2020-5-30 22:06:28

看看
页: [1] 2
查看完整版本: 编写一个函数parse,实现计算器功能