首页 > 解决方案 > 如何区分计算器的运算符和负数?

问题描述

尽管遇到问题,但我正在尝试制作自己的“计算器”。当我将运算符和数字分开时,负数不起作用。因为'-'符号被算作一个操作符。现在我的问题是如何区分两个运算符和包括负数的数字?

我不希望负数适用于我当前的代码,尽管我正在努力让它们工作。
关于我该怎么做的任何想法?

这是计算器的完整代码。

import re

def calc(equation):

    equationList = re.findall('[+-/*]|\d+', equation)
    operators = [i for i in equationList if not i.isdigit()]
    numbers = [i for i in equationList if i.isdigit()]
    operators.insert(0,'+')
    answer = 0

    for i, operator in enumerate(operators):
        number = numbers[i]
        if operator == '+': answer += int(number)
        if operator == '-': answer -= int(number)
        if operator == '*': answer *= int(number)
        if operator == '/': answer /= int(number)

    print(f'Equation: {"".join(equationList)}\nAnswer: {answer}')


while True:
    calc(input('>>> '))

当我尝试运行带有负数的方程时,出现错误:

>>> -5*10

Traceback (most recent call last):                                                                                                                                                 
  File "main.py", line 22, in <module>                                                                                                                                             
    calc(input('>>> '))                                                                                                                                                            
  File "main.py", line 12, in calc                                                                                                                                                 
    number = numbers[i]                                                                                                                                                            
IndexError: list index out of range

标签: pythonregexpython-3.xcalculator

解决方案


所以,我有很多信息给你,但它们非常相关。我还彻底改变了你的代码:

除非您需要诸如在每个负数周围有括号/空格之类的东西,否则轻松地将运算符和数字分开是行不通的。但这不仅会使您无法在计算器中输入常规的、未格式化的方程式,而且还要求您将负数视为特殊数。它们是什么,但这不是必需的。这是因为您基本上可以忽略它们是否定的。我建议的代码更改将更容易让您处理任何运算符。

任何负数都可以分解为一个运算:-x 与 0 - x 相同。问题是:什么时候应该加零?有两种情况:当第一个输入是负号时,以及当另一个运算符后面有一个负号时。您需要做的就是添加一些代码来处理这些条件。让我们看一些例子:

>>> -2+5
3
>>> 5+-2
3
>>> (1/9)^(-1/2)
3
>>> (2+(-1))*5-2
43

您的方法中的否定问题来自这样一个事实,即当您将运算符与 numbers 分开时您不知道接下来应该发生什么:运算符或数字(这是上述所有示例的问题)。


一种解决方案是跟踪所有号码的位置!这样做可以让您确切地知道每个数字之间有多少个运算符,并且您可以通过它找出哪些数字是负数(或者您应该在哪里添加零)。

我已经为此重写了您的代码,它非常不同,但主要思想仍然存在。请看下面的代码:

import re

# Takes care of applying the operation on the left number given the right number
def applyOperation(operator, left, right):
    answer = left
    if operator == '(':
        return NotImplemented
    elif operator == ')':
        return NotImplemented
    elif operator == '^':
        return NotImplemented
    elif operator == '*': answer *= int(right)
    elif operator == '/': answer /= int(right)
    elif operator == '+': answer += int(right)
    elif operator == '-': answer -= int(right)
    else:
        print("Error. Only '*', '/', '+',and '-' are allowed at the moment.")
        # You could also allow a period, exponents (^), modulo, exponential, etc.
        exit(1)
    return answer

def calc(equation):
    """
    Magical calculator (It handles negative numbers)

    DISCLAIMER: 
     -This version does not allow parentheses or float inputs (but does allow float outputs)
     -It also does not follow the order of operations
    """
    numIndices = [m.span() for m in re.finditer("\d+", equation)]
    prevNumber = 0
    prevEnd = ''

    for numIndex in numIndices:
        number = float(equation[numIndex[0]:numIndex[1]])

        # If at the start, just add the number
        if numIndex[0] == 0:
            prevNumber = number
            prevEnd = numIndex[1]
            continue

        # Starting at the second spot of the equation is special
        if numIndex[0] == 1:
            # Remember this for order of operations (if implemented)
            if equation[0] == "(":
                # I think handling these would be best done recursively
                # Or you could split on all parentheses and compute each in turn
                # Or ...
                return NotImplemented
            # It's a negative number
            elif equation[0] == "-":
                prevNumber -= number
                prevEnd = numIndex[1]
                continue
            else:
                print("Error. Only numbers, '-' and '(' are allowed at the " 
                      +"beginning of the equation.")
                # You could allow a period as well.
                exit(1)

        # If reached here, then should have passed the first number
        # Extract relevant operators and remove any spaces
        operators = equation[prevEnd:numIndex[0]]
        operators = "".join(operators.split())
        if len(operators) == 1:
            prevNumber = applyOperation(operators[0], prevNumber, number)

        elif len(operators) == 2:
            if (operators[1] == '-'):
                prevNumber = applyOperation(operators[0], prevNumber, -number)
            else:
                print("Error. Currently, the second operator must always be a '-'.")
                exit(1)

        # If it reaches here, then parentheses are probably involved 
        # or syntax is probably incorrect
        else:
            print("Error. Only two operators are currently allowed between numbers." 
                  + " The second one always being a '-'.")
            # You could allow all sorts of nesting with parentheses if you want.
            exit(1)
        prevEnd = numIndex[1]

    # Do not display the decimal places if they are all 0
    prevNumber = int(prevNumber) if prevNumber-int(prevNumber) == 0 else prevNumber
    print("Equation:", equation,"\nAnswer:",prevNumber)


while True:
    calc(input('>>> '))

计算器不是玩笑!xD

PS它也接受只有字母的方程。


推荐阅读