python实现计算器

python实现计算器

参考
https://blog.csdn.net/a971956955/article/details/81489914
https://www.cnblogs.com/dbefb/p/12346648.html
https://next.xuetangx.com/learn/THU08091000367/THU08091000367/1516221/exercise/1385889

1.题目描述

实现一个计算器的控制台程序,支持加减乘除、乘方、括号、小数点,运算符优先级为括号>乘方>乘除>加减,同级别运算按照从左向右的顺序计算

1.1输入描述

  • 数字包括"0123456789",小数点为".",运算符包括:加("+")、减("-")、乘("*")、除("/")、乘方("^",注:不是**!)、括号("()")
  • 需要从命令行参数读入输入,例如提交文件为main.py,可以用python3 main.py "1+2-3+4"的方式进行调用,Java程序也是类似的,如果你的程序需要通过键盘输入,那么是不符合要求的,例如python使用input()来等待用户输入,这会因为自动评测时不会有用户输入所以不会有任何结果
  • 输入需要支持空格,即 python3 main.py "1 + 2 - 3 + 4" 也需要程序能够正确给出结果,Java程序也是类似的
  • 所有测试用例中参与运算的非零运算数的绝对值范围保证在 109-10(-10) 之内, 应该输出运算结果时非零运算结果绝对值也保证在该范围内

1.2输出描述

  • 数字需要支持小数点,输出结果取10位有效数字,有效数字位数不足时不能补0
  • 对于不在输入描述内的输入,输出INPUT ERROR
  • 对于格式不合法(例如括号不匹配等)的输入,输出 FORMAT ERROR
  • 对于不符合运算符接收的参数范围(例如除0等)的输入,输出VALUE ERROR
  • 对于2、3、4的情况,输出即可,不能抛出异常
  • 同时满足2、3、4中多个条件时,以序号小的为准

1.3样例

输入: 1 + 2 - 3 + 4
输出: 4
输入: 1 + 2 - 3 + 1 / 3
输出: 0.3333333333
输入: 1 + + 2
输出: FORMAT ERROR
输入: 1 / 0
输出: VALUE ERROR
输入: a + 1
输出: INPUT ERROR

2.解决方案

2.1思路

  • 需要格外注意括号,实现运算符的优先级实现
  • 当一个表达式中不含括号的时候是比较好处理的,所以要想办法去掉括号。一个方法是先计算括号内的表达式,然后用计算结果代替这个括号
  • 首先将数字和运算符提取到列表保存,然后对列表中元素逐一处理
  • 去括号:递归的去除最内层的括号
  • 去加减乘除号:依次处理

2.2表达式转变成列表

关于正则表达式请见我的随笔正则表达式

def equation_to_list(equation):
    equation_list = re.findall(r"[\d\.]+|\(|\+|\-|\*|\/|\)+", equation)
    return equation_list
equation = "(5.4+3.6/3)*1.0"
print(equation_to_list(equation))
# ['(', '5.4', '+', '3.6', '/', '3', ')', '*', '1.0']

2.3完整代码

import re
import sys


def conversionFormula(formula):
    format_list = re.findall('[\w\.]+|\(|\+|\-|\*|\/|\^|\)', formula)
    switch = 0
    switch2 = 0
    count = 0
    for i in format_list:
        if i == '(' or i == ')':  # 进行括号符号的判断
            switch2 += 1
    for i in format_list:
        if i == '+' or i == '-' or i == '*' or i == '/' or i == '^':  # 进行加减乘除乘方符号的判断
            switch = 1
            break
    if switch != 1:
        print('INPUT ERROR')
        return 'ERROR'
    for i in format_list:  # 进行一些错误的判断
        if i == '+' or i == '-' or i == '*' or i == '/':
            if format_list[count - 1] == '+' or format_list[count - 1] == '-' or \
                    format_list[count - 1] == '*' or format_list[count - 1] == '/' or \
                    format_list[count + 1] == '+' or format_list[count + 1] == '-' or \
                    format_list[count + 1] == '*' or format_list[count + 1] == '/':
                print('FORMAT ERROR')
                return 'ERROR'
            elif i == '/' and format_list[count + 1] == '0':
                print('VALUE ERROR')
                return 'ERROR'
        elif i.isalpha():
            print('INPUT ERROR')
            return 'ERROR'
        count += 1
    if switch2 % 2 != 0:
        print('FORMAT ERROR')
        return 'ERROR'
    return format_list


def remove_bracket(formula):
    leftBracket = 0
    count = 0  # 用遍历列表进行计数
    for i in formula:
        if i == '(':  # 记录最内侧左括号的位置
            leftBracket = count
        elif i == ')':
            smallestFomula = formula[leftBracket + 1:count]  # 提取最内层括号里式子
            smallestFomulaAnswer = calculator(smallestFomula)  # 调用calculator方法进行计算
            if smallestFomulaAnswer < 0:          # 更新式子,对去括号后的+-,--情况进行分析
                if formula[leftBracket - 1] == '-':
                    formula[leftBracket - 1] = '+'
                    temp = formula[:leftBracket]
                    temp.append(str(abs(smallestFomulaAnswer)))
                    formula = temp + formula[count + 1:]
                elif formula[leftBracket - 1] == '+':
                    formula[leftBracket - 1] = '-'
                    temp = formula[:leftBracket]
                    temp.append(str(abs(smallestFomulaAnswer)))
                    formula = temp + formula[count + 1:]
                else:
                    temp = formula[:leftBracket]
                    temp.append(str(smallestFomulaAnswer))
                    formula = temp + formula[count + 1:]
            else:
                temp = formula[:leftBracket]
                temp.append(str(smallestFomulaAnswer))
                formula = temp + formula[count + 1:]
            return remove_bracket(formula)  # 递归,进行新式子的去括号分析
        count += 1
    return formula  # 返回无括号的最终式子


def calculator(formula):
    count = 0
    for i in formula:  # 先处理乘方、乘除
        if i == '^':
            formula[count - 1] = str(float(formula[count - 1]) ** float(formula[count + 1]))
            del (formula[count])
            del (formula[count])
            return calculator(formula)
        elif i == '*':
            formula[count - 1] = str(float(formula[count - 1]) * float(formula[count + 1]))
            del (formula[count])
            del (formula[count])
            return calculator(formula)
        elif i == '/':
            formula[count - 1] = str(float(formula[count - 1]) / float(formula[count + 1]))
            del (formula[count])
            del (formula[count])
            return calculator(formula)
        count += 1

    count = 0
    if formula[0] == '-':  # 处理第一个字符是’-’的情况
        formula[1] = formula[0] + formula[1]
        del (formula[0])
    for i in formula:  # 处理加减
        if i == '+':
            formula[count - 1] = str(float(formula[count - 1]) + float(formula[count + 1]))
            del (formula[count])
            del (formula[count])
            return calculator(formula)
        elif i == '-':
            formula[count - 1] = str(float(formula[count - 1]) - float(formula[count + 1]))
            del (formula[count])
            del (formula[count])
            return calculator(formula)
        count += 1
    return float(formula[0])  # 返回float型的运算结果


if __name__ == '__main__':

    formula = "".join(sys.argv[1:])
    formula = conversionFormula(formula)

    if formula != 'ERROR':  # 错误判断
        formula = remove_bracket(formula)
        answer = calculator(formula)
        if float(answer).is_integer() == True:
            answer = int(answer)
        else:
            answer = format(answer, '.10f')  # 空格补0,不足位数不补0
            answer = float(str(answer).rstrip('0'))
        print(answer)
    else:
        a = 1

posted @ 2020-04-02 15:04  happy_fan  阅读(2083)  评论(0编辑  收藏  举报