#python #if-statement
#python #if-statement
Вопрос:
В настоящее время я создаю калькулятор на Python, и я столкнулся с небольшой проблемой: у меня есть 28 условий в моем операторе if-else:
if operation0 == " " and operation1 == " " and operation2 == " ": # First operation is addition
print(number0 number1 number2 number3)
elif operation0 == " " and operation1 == " " and operation2 == "*":
print(number0 number1 number2 * number3)
elif operation0 == " " and operation1 == " " and operation2 == "^":
print(number0 number1 number2 ** number3)
elif operation0 == " " and operation1 == "*" and operation2 == " ":
print(number0 number1 * number2 number3)
elif operation0 == " " and operation1 == "*" and operation2 == "*":
print(number0 number1 * number2 * number3)
elif operation0 == " " and operation1 == "*" and operation2 == "^":
print(number0 number1 * number2 ** number3)
elif operation0 == " " and operation1 == "^" and operation2 == " ":
print(number0 number1 ** number2 number3)
elif operation0 == " " and operation1 == "^" and operation2 == "*":
print(number0 number1 ** number2 * number3)
elif operation0 == " " and operation1 == "^" and operation2 == "^":
print(number0 number1 ** number2 ** number3)
elif operation0 == "*" and operation1 == " " and operation2 == " ": # First operation is multiplication
print(number0 * number1 number2 number3)
elif operation0 == "*" and operation1 == " " and operation2 == "*":
print(number0 * number1 number2 * number3)
elif operation0 == "*" and operation1 == " " and operation2 == "^":
print(number0 * number1 number2 ** number3)
elif operation0 == "*" and operation1 == "*" and operation2 == " ":
print(number0 * number1 * number2 number3)
elif operation0 == "*" and operation1 == "*" and operation2 == "*":
print(number0 * number1 * number2 * number3)
elif operation0 == "*" and operation1 == "*" and operation2 == "^":
print(number0 * number1 * number2 ** number3)
elif operation0 == "*" and operation1 == "^" and operation2 == " ":
print(number0 * number1 ** number2 number3)
elif operation0 == "*" and operation1 == "^" and operation2 == "*":
print(number0 * number1 ** number2 * number3)
elif operation0 == "*" and operation1 == "^" and operation2 == "^":
print(number0 * number1 ** number2 ** number3)
elif operation0 == "^" and operation1 == " " and operation2 == " ": # First operation is exponentiation
print(number0 ** number1 number2 number3)
elif operation0 == "^" and operation1 == " " and operation2 == "*":
print(number0 ** number1 number2 * number3)
elif operation0 == "^" and operation1 == " " and operation2 == "^":
print(number0 ** number1 number2 ** number3)
elif operation0 == "^" and operation1 == "*" and operation2 == " ":
print(number0 ** number1 * number2 number3)
elif operation0 == "^" and operation1 == "*" and operation2 == "*":
print(number0 ** number1 * number2 * number3)
elif operation0 == "^" and operation1 == "*" and operation2 == "^":
print(number0 ** number1 * number2 ** number3)
elif operation0 == "^" and operation1 == "^" and operation2 == " ":
print(number0 ** number1 ** number2 number3)
elif operation0 == "^" and operation1 == "^" and operation2 == "*":
print(number0 ** number1 ** number2 * number3)
elif operation0 == "^" and operation1 == "^" and operation2 == "^":
print(number0 ** number1 ** number2 ** number3)
else:
print("Error")
Ничего из того, что я пробовал, не сработало, и я не смог найти на этом сайте ничего, что помогло бы мне сжать код. Такое количество повторяющихся elif неразумно, и любое сокращение будет оценено.
Комментарии:
1. Я думаю, что лучше всего было бы реализовать алгоритм маневровой площадки .
Ответ №1:
ОТКАЗ ОТ ОТВЕТСТВЕННОСТИ: в решении могут использоваться различные концепции, которые недостаточно актуальны для объяснения здесь.
Чтобы получить приоритет, вам нужно будет правильно проанализировать входные данные. Для этого существует несколько методов; одним из распространенных является алгоритм маневровой площадки Дейкстры.
Поскольку это всего лишь пример, мы откажемся от хорошей практики (обработка ошибок, классы) для более сжатого кода.
Во-первых, нам нужно перечислить прецеденты. Более высокий приоритет означает, что оператор имеет более высокий приоритет, поэтому он выполняется раньше.
precedences = {
'^': 3,
'*': 2, '/': 2,
' ': 1, '-': 1
}
Затем нам нужно связать действия с каждым оператором. Для этого мы можем использовать функции в operator
модуле:
from operator import pow, truediv, mul, add, sub
do = {
'^': pow,
'*': mul, '/': truediv,
' ': add, '-': sub
}
Наконец, нам нужно реализовать логику, которая решает, когда оценивать выражение. Во-первых, у нас на одно число больше, чем операция, поэтому мы помещаем его в стек:
def shunt(numbers, operations):
stack = [numbers.pop(0)]
operators = []
Затем мы обрабатываем каждую пару оператор-число.
while len(numbers):
operator = operations.pop(0)
precedence = precedences[operator]
Операция вычисляется (с использованием do
словаря), когда она имеет более высокий приоритет (выполняется раньше), чем текущая операция. Мы удаляем левый и правый операнды из стека и выполняем поиск соответствующей функции do
для оценки результата:
while operators and precedences[operators[-1]] >= precedence:
[left, right], stack[-2:] = stack[-2:], []
stack.append(do[operators.pop()](left, right))
Затем мы добавляем текущий оператор и число в стеки:
operators.append(operator)
stack.append(numbers.pop(0))
После того, как все числа и операторы были израсходованы, мы оцениваем остальные операторы до тех пор, пока не останется только одно число, и возвращаем это:
while len(stack) > 1:
[left, right], stack[-2:] = stack[-2:], []
stack.append(do[operators.pop()](left, right))
return stack[0]
Собрать все это вместе (попробуйте онлайн!):
from operator import pow, truediv, mul, add, sub
precedences = {
'^': 3,
'*': 2, '/': 2,
' ': 1, '-': 1
}
do = {
'^': pow,
'*': mul, '/': truediv,
' ': add, '-': sub
}
def shunt(numbers, operations):
stack = [numbers.pop(0)]
operators = []
while len(numbers):
operator = operations.pop(0)
precedence = precedences[operator]
while operators and precedences[operators[-1]] >= precedence:
[left, right], stack[-2:] = stack[-2:], []
stack.append(do[operators.pop()](left, right))
operators.append(operator)
stack.append(numbers.pop(0))
while len(stack) > 1:
[left, right], stack[-2:] = stack[-2:], []
stack.append(do[operators.pop()](left, right))
return stack[0]
Ответ №2:
Порядок операций делает это сложным, но не невозможным:
# helper function to do an operation
def doop(num1, op, num2):
if op == "^":
return num1 ** num2
if op == " ":
return num1 num2
if op == "-":
return num1 - num2
if op == "*":
return num1 * num2
if op == "/":
return num1 / num2
# if we don't recognize the operation then error
raise Exception("Invalid operation.")
# have a list of sets with operator precedence
precedence = [
{"^"},
{"*", "/"},
{" ", "-"}
]
# hard coded values for testing
nums = [1, 2, 3, 4]
ops = [" ", "-", "*"]
# this represents 1 2 - 3 * 4
# start at highest to lowest precedence
for prec in precedence:
# we have to use a while loop to have manual control of `i`
i = 0
while i < len(ops):
# store the current operation
op = ops[i]
# if the operation isn't in the current precedence level we skip it
if op in prec:
# we can get rid of the operation to evaluate it
ops.pop(i)
# we can merge the two numbers around the operation into one
# by performing the calculation
nums[i:i 2] = [doop(nums[i], op, nums[i 1])]
# we need to decrease i so we don't skip over the next operation
i -= 1
i = 1
if len(nums) != 1:
raise Exception("Invalid operation count.")
print(nums[0]) # -9
Комментарии:
1. аплет, где объяснение
2. Я думаю, что более специализированное исключение будет работать лучше, например
ArithmeticError
.
Ответ №3:
При выполнении общих процессов с несколькими значениями вы должны использовать списки вместо отдельных переменных. Это позволяет вам применять общую логику к элементам и манипулировать ими на основе индексов, которые вы можете хранить в переменных:
def compute(*operNums):
operNums = list(operNums)
numbers = operNums[::2] # [number0,number1,number2,number3]
operations = operNums[1::2] # [operation0,operation1,operation2]
while operations: # process list until all operations performed
for op in ("^","**","*"," "): # find highest priority operation
if op not in operations: continue
i = operations.index(op) # index of operation
operations.pop(i) # remove completed operation
if op in ["^","**"]: numbers[i] **= numbers.pop(i 1) # remove right side
elif op == "*": numbers[i] *= numbers.pop(i 1) # left side number
elif op == " ": numbers[i] = numbers.pop(i 1) # is replaced by result
else: return "ERROR"
return numbers[0]
print(compute(1," ",2,"**",3,"*",5)) # 41
Ответ №4:
Вы могли бы использовать библиотеку операторов и попробовать что-то вроде
from operator import pow, truediv, mul, add, sub
operators = {
' ': add,
'-': sub,
'*': mul,
'/': truediv
}
def calculate(s):
if s.isdigit():
return float(s)
for c in operators.keys():
left, operator, right = s.partition(c)
if operator in operators:
return operators[operator](calculate(left), calculate(right))
calc = input("Type calculation:n")
print("Answer: " str(calculate(calc)))
Некоторые другие решения также доступны по адресу https://levelup.gitconnected.com/3-ways-to-write-a-calculator-in-python-61642f2e4a9a
Комментарии:
1. как и ответ Карла, не обрабатывает приоритет