Reputation: 11
I'm writing a program for my intro programming class and I need to make a calculator that prints out the results like a history. I'm doing it in a way that the first number, the arithmetic operation and second number are separate objects in a list but I need to combine them into a complete object in a list. I've tried several ways to do this but each time it will either crash or not work exactly how it should.
history = []
first_number = int(input("please input your first number"))
second_number = int(input("please input your second number"))
operator = input("ADD, SUBTRACT, DIVIDE, MULTIPLY, CHOOSE again or STOP? ").lower()
def add():
return(first_number + second_number)
def problemAdd():
return(first_number, "+", second_number)
while operator != "stop":
if operator == "add":
print("the problem was:", first_number, "+", second_number, "=", add())
history.append (problem())
print(history)
first_number = int(input("please input your first number"))
second_number = int(input("please input your second number"))
operator = input("ADD, SUBTRACT, DIVIDE, MULTIPLY, CHOOSE again or STOP? ").lower()
Now this part of the code I hope it's enough to spot a problem. And this is what it outputs:
please input your first number2
please input your second number2
would you like to ADD, SUBTRACT, DIVIDE, MULTIPLY, CHOOSE again or STOP? add
the problem was: 2 + 2 = 4
[(2, '+', 2)]
please input your first number1
please input your second number2
would you like to ADD, SUBTRACT, DIVIDE, MULTIPLY, CHOOSE again or STOP? add
the problem was: 1 + 2 = 3
[(2, '+', 2), (1, '+', 2)]
please input your first number
I ran through it twice to show how each individual problem is displayed.
Upvotes: 1
Views: 60
Reputation: 54213
# lst = [(2, '+', 2)]
for tpl in lst:
operation = " ".join(map(str,tpl))
# map(str, tpl) returns an object where every element in tpl is mapped
# using the str function. str(object) returns the value of object as a
# string.
result = eval(operation)
# eval IS A BAD IDEA, BUT SIMPLE TO IMPLEMENT
print("{} = {}".format(operation, result))
It's a little unclear if this is what you're trying to do. I'm not sure where the [ ..., "3 - 2 = 1"]
part from your question comes in. Maybe this will help, though?
If you only ever have two operands and one operator (e.g. everything is of the form a ? b
where ?
is an operator, then this is much safer:
def do_operation(operation):
import operator
operand_1, operator, operand_2 = operation
try:
f = {"+": operator.add, "-": operator.sub,
"/": operator.truediv, "*": operator.mul,
"//": operator.floordiv, "%": operator.mod}[operator]
except KeyError:
raise ValueError("Invalid operator")
return f(operand_1, operand_2)
for tpl in lst:
operation = " ".join(map(str,tpl))
result = do_operation(tpl)
print("{} = {}".format(operation, result))
history = []
first_number = int(input("please input your first number"))
second_number = int(input("please input your second number"))
# what do you do if the user doesn't enter a number? Your program crashes
operator = input("ADD, SUBTRACT, DIVIDE, MULTIPLY, CHOOSE again or STOP? ").lower()
op_mapping = {"add":"+", "subtract":"-", "divide":"/", "multiply":"*"}
if operator in op_mapping: # this will exclude 'choose' and 'stop'
operator = op_mapping[operator]
elif operator == 'choose': # handle it
elif operator == 'stop': # handle it, these are up to you
else: # invalid input, handle it.
# NEW
operation = (first_number, operator, second_number)
# this makes it easier to refer to all three at once.
def calculate(operation):
"""Calculates the result based on which operator is used"""
import operator
operand_1, operator, operand_2 = operation
try:
f = {"+": operator.add, "-": operator.sub,
"/": operator.truediv, "*": operator.mul,
"//": operator.floordiv, "%": operator.mod}[operator]
except KeyError:
raise ValueError("Invalid operator")
return f(operand_1, operand_2)
## while operator != "stop": # you're gonna handle this above
## if operator == "add": # we modified it so our mapping handles all if cases
## print("the problem was:", first_number, "+", second_number, "=", add())
## history.append (problem())
## print(history)
## first_number = int(input("please input your first number"))
## second_number = int(input("please input your second number"))
## operator = input("ADD, SUBTRACT, DIVIDE, MULTIPLY, CHOOSE again or STOP? ").lower()
human_readable = " ".join(map(str,operation))
history.append(human_readable)
print("{} = {}".format(human_readable, calculate(operation))
print(history)
# LOOP AS NEEDED, IMPLEMENTED BY YOU.
Mind you if I were to do a complete rewrite it would probably look like:
def get_input():
"""Get user input for the calculation"""
inputprompt = """Return the result of a calculation, based on user input.
Your input must be of the form X ? Y where X, Y are any number and ? is one of:
+, -, /, //, *, %
Please include spaces between operand and operator, or STOP to stop.
>> """
return input(inputprompt)
def calculate(operation):
"""Calculates the result based on which operator is used"""
import operator
operand_1, operator, operand_2 = operation
try:
operand_1, operand_2 = float(operand_1), float(operand_2)
except ValueError:
raise ValueError("Invalid operand")
try:
f = {"+": operator.add, "-": operator.sub,
"/": operator.truediv, "*": operator.mul,
"//": operator.floordiv, "%": operator.mod}[operator]
except KeyError:
raise ValueError("Invalid operator")
return f(operand_1, operand_2)
def main():
from collections import deque
history = deque()
# a deque is a list that allows easy popping and appending from left OR right
MAX_HISTORY_LENGTH = 10
while True
print("CALCULATOR:\n\n")
readable = get_input()
if "stop" in readable.lower():
break
operation = readable.split()
history.append(readable)
if len(history) > MAX_HISTORY_LENGTH:
history.popleft()
print("{} = {}".format(readable, calculate(operation))
input(" ( press ENTER to continue ) ")
main()
# we love functional programming!
Upvotes: 2