I need to extend the given calculator program to record the calculations, and recall them as a list using an additional command '?'.
Things to do:
Declare a list to store the previous operations
Save the operator, operands, and the results as a single string, for each operation after each calculation
implement a history() function to handle the operation '?'
Display the complete saved list of operations (in the order of execution) using a new command ‘?’
If there are no previous calculations when the history '?' command is used, you can display the following message "No past calculations to show"
Can someone help me, please?
return a+b
def subtract(a,b):
return a-b
def multiply (a,b):
return a*b
def divide(a,b):
try:
return a/b
except Exception as e:
print(e)
def power(a,b):
return a**b
def remainder(a,b):
return a%b
def select_op(choice):
if (choice == '#'):
return -1
elif (choice == '$'):
return 0
elif (choice in ('+','-','*','/','^','%')):
while (True):
num1s = str(input("Enter first number: "))
print(num1s)
if num1s.endswith('$'):
return 0
if num1s.endswith('#'):
return -1
try:
num1 = float(num1s)
break
except:
print("Not a valid number,please enter again")
continue
while (True):
num2s = str(input("Enter second number: "))
print(num2s)
if num2s.endswith('$'):
return 0
if num2s.endswith('#'):
return -1
try:
num2 = float(num2s)
break
except:
print("Not a valid number,please enter again")
continue
if choice == '+':
result = add(num1, num2)
elif choice == '-':
result = subtract(num1, num2)
elif choice == '*':
result = multiply(num1, num2)
elif choice == '/':
result = divide(num1, num2)
elif choice == '^':
result = power(num1, num2)
elif choice == '%':
result = remainder(num1, num2)
else:
print("Something Went Wrong")
else:
print("Unrecognized operation")
while True:
print("Select operation.")
print("1.Add : + ")
print("2.Subtract : - ")
print("3.Multiply : * ")
print("4.Divide : / ")
print("5.Power : ^ ")
print("6.Remainder: % ")
print("7.Terminate: # ")
print("8.Reset : $ ")
print("8.History : ? ")
# take input from the user
choice = input("Enter choice(+,-,*,/,^,%,#,$,?): ")
print(choice)
if(select_op(choice) == -1):
#program ends here
print("Done. Terminating")
exit()```
You need to declare function history() and list,
last_calculation = []
def history():
global last_calculation
if last_calculation == []:
print("No past calculations to show")
else:
for i in last_calculation:
print(*i) #for single line
Then in the if loop add below code to end of the operations,
last_calculation.append(result)
Then trigger history() function, use 'continue' to make operation after the call history()
if choice=='?':
history()
continue
To save the history, you can add a global variable which is an empty list. Like this:
history = []
...
def record_history(*args):
history.append(args)
def select_op(choice):
...
record_history(choice, num1, num2, result)
...
This is not the most cleanest solution, but the simplest one since you are only using functions. Ideally functions should not have any side effects and should not depend on the "state" of the program. To save any kind of "state" refactoring this implementation into classes would make things more clean. Something like
class Calculator:
def __init__(self):
self.history = []
def record_history(self, *args):
self.history.append(args)
def select_op(self, choice):
...
self.record_history(choice, num1, num2, result)
...
Tips
Make your life simpler by using the standard library
The operator library provides functions like add, sub, mul etc.
The cmd.Cmd class can be used to build interactive consoles easily.
This is my answer to the problem you face. I have created this and checked it.
calculations = []
def record_history(args):
calculations.append(args)
def history():
if calculations == []:
print("No past calculations to show")
else:
for i in calculations:
print(i)
def add(a,b):
return a+b
def subtract(a,b):
return a-b
def multiply (a,b):
return a*b
def divide(a,b):
try:
return a/b
except Exception as e:
print(e)
def power(a,b):
return a**b
def remainder(a,b):
return a%b
def select_op(choice):
if choice == '#':
return -1
elif choice == '$':
return 0
elif choice in ('+', '-', '*', '/', '^', '%'):
while True:
num1s = input("Enter first number: ")
print(num1s)
if num1s.endswith('$'):
return 0
if num1s.endswith('#'):
return -1
try:
num1 = float(num1s)
break
except:
print("Not a valid number, please enter again")
continue
while True:
num2s = input("Enter second number: ")
print(num2s)
if num2s.endswith('$'):
return 0
if num2s.endswith('#'):
return -1
try:
num2 = float(num2s)
break
except:
print("Not a valid number, please enter again")
continue
result = 0.0
last_calculation = ""
if choice == '+':
result = add(num1, num2)
elif choice == '-':
result = subtract(num1, num2)
elif choice == '*':
result = multiply(num1, num2)
elif choice == '/':
result = divide(num1, num2)
elif choice == '^':
result = power(num1, num2)
elif choice == '%':
result = remainder(num1, num2)
else:
print("Something Went Wrong")
last_calculation = "{0} {1} {2} = {3}".format(num1, choice, num2, result)
print(last_calculation)
record_history(last_calculation)
elif choice == '?':
history()
else:
print("Unrecognized operation")
while True:
print("Select operation.")
print("1.Add : + ")
print("2.Subtract : - ")
print("3.Multiply : * ")
print("4.Divide : / ")
print("5.Power : ^ ")
print("6.Remainder: % ")
print("7.Terminate: # ")
print("8.Reset : $ ")
print("8.History : ? ")
# take input from the user
choice = input("Enter choice(+,-,*,/,^,%,#,$,?): ")
print(choice)
if select_op(choice) == -1:
#program ends here
print("Done. Terminating")
break
Related
I've tried Simple Python Calculator with Maintaining past history with it. The word "None" is getting printed after each calculations. How to remove that "None" word from my code
Here is my code for python calculator!!
calculations = []
def record_history(args):
calculations.append(args)
def history():
if calculations == []:
print("No past calculations to show")
else:
for i in calculations:
print(i)
def add(a,b):
return a+b
def subtract(a,b):
return a-b
def multiply (a,b):
return a *b
def divide(a,b):
try:
return a/b
except Exception as e:
print(e)
def power(a,b):
return a**b
def remainder(a,b):
return a % b
def select_op(choice):
if choice == '#':
return -1
elif (choice == '$'):
return 0
elif (choice in ('+','-','*','/','^','%')):
while (True):
num1s = (input("Enter first number: "))
print(num1s)
if num1s.endswith('$'):
return 0
if num1s.endswith('#'):
return -1
try:
num1 = float(num1s)
break
except:
print("Not a valid number,please enter again")
continue
while (True):
num2s = str(input("Enter second number: "))
print(num2s)
if num2s.endswith('$'):
return 0
if num2s.endswith('#'):
return -1
try:
num2 = float(num2s)
break
except:
print("Not a valid number,please enter again")
continue
last_calculation = ""
if choice == '+':
result = add(num1, num2)
elif choice == '-':
result = subtract(num1, num2)
elif choice == '*':
result = multiply(num1, num2)
elif choice == '/':
result = divide(num1, num2)
elif choice == '^':
result = power(num1, num2)
elif choice == '%':
result = remainder(num1, num2)
else:
print("Something Went Wrong")
last_calculation = "{0} {1} {2} = {3}".format(num1, choice, num2, result)
print((last_calculation ))
print((record_history(last_calculation)))
elif choice == "?":
history()
else:
print("Unrecognized operation")
while True:
print("Select operation.")
print("1.Add : + ")
print("2.Subtract : - ")
print("3.Multiply : * ")
print("4.Divide : / ")
print("5.Power : ^ ")
print("6.Remainder: % ")
print("7.Terminate: # ")
print("8.Reset : $ ")
print("8.History : ? ")
# take input from the user
choice = input("Enter choice(+,-,*,/,^,%,#,$,?): ")
print(choice)
if(select_op(choice) == -1):
#program ends here
print("Done. Terminating")
exit()
The output is,
Select operation.
1.Add : +
2.Subtract : -
3.Multiply : *
4.Divide : /
5.Power : ^
6.Remainder: %
7.Terminate: #
8.Reset : $
8.History : ?
Enter choice(+,-,*,/,^,%,#,$,?): ?
No past calculations to show
Select operation.
1.Add : +
2.Subtract : -
3.Multiply : *
4.Divide : /
5.Power : ^
6.Remainder: %
7.Terminate: #
8.Reset : $
8.History : ?
Enter choice(+,-,*,/,^,%,#,$,?): -
Enter first number: 2
Enter second number: 3
2.0 - 3.0 = -1.0
None
Select operation.
1.Add : +
2.Subtract : -
3.Multiply : *
4.Divide : /
5.Power : ^
6.Remainder: %
7.Terminate: #
8.Reset : $
8.History : ?
Enter choice(+,-,*,/,^,%,#,$,?): ?
2.0 - 3.0 = -1.0
Select operation.
1.Add : +
2.Subtract : -
3.Multiply : *
4.Divide : /
5.Power : ^
6.Remainder: %
7.Terminate: #
8.Reset : $
8.History : ?
Enter choice(+,-,*,/,^,%,#,$,?): #
Done. Terminating
How to Remove the extra None ...
The problem is here:
print((record_history(last_calculation)))
The functoin record_history doesn't return a value, so it implicitly returns None. Instead of trying to print the result of the call (i.e., None), just call it by replacing the above with:
record_history(last_calculation)
I need to reset this calculator when user enter "$" instead first or second input number or user enter "$" end of the input number (ex: 5$,20$).
the (a,b) is input number1 and number2. it was assigned as global varibles.
select_op(choice) is function, running the operation that user need. input_function() is function for input two numbers.
# Functions for arithmetic operations.
def add(a,b):
return (a+b) # 'a' and 'b' will add.
def subtract(a,b):
return (a-b) # 'b' substract from 'a'.
def multiply(a,b):
return (a*b) #'a' multiply by 'b'.
def divide(a,b):
if b == 0 : .
return None
else:
return (a/b) # 'a' divided by 'b'.
def power(a,b):
return (a**b) # 'a' power of 'b'.
def remainder(a,b):
if b == 0:
return None
else:
return (a%b) # reminder of 'a' divided by 'b'.
#this function for out put of operation
def select_op(choice): #this function will select operation
if choice == "+":
input_function()
print(a,' + ',b,' = ',add(a,b))
elif choice == "-":
input_function()
print(a,' - ',b,' = ',subtract(a,b))
elif choice == "*":
input_function()
print(a,' * ',b,' = ',multiply(a,b))
elif choice == "/":
input_function()
if b==0:
print("float division by zero")
print(a,' / ',b,' = ',divide(a,b))
elif choice == "^":
input_function()
print(a,' ^ ',b,' = ',power(a,b))
elif choice == "%":
input_function()
if b==0:
print("float division by zero")
print(a,' % ',b,' = ',remainder(a,b))
elif choice == "#": #if choice is '#' program will terminate.
return -1
elif choice == "$": #if choice is '$' program reset.
return None
else:
print("Unrecognized operation")
#this function for input two operands.
def input_function():
number1=float(input("Enter first number: "))
number2=float(input("Enter second number: "))
global a,b
a=number1
b=number2
return a,b
#loop repeat until user need to terminate.
while True:
print("Select operation.")
print("1.Add : + ")
print("2.Subtract : - ")
print("3.Multiply : * ")
print("4.Divide : / ")
print("5.Power : ^ ")
print("6.Remainder: % ")
print("7.Terminate: # ")
print("8.Reset : $ ")
# take input from the user
choice = input("Enter choice(+,-,*,/,^,%,#,$): ")
print(choice)
if(select_op(choice) == -1):
#program ends here
print("Done. Terminating")
exit()
Be sure to check whether the string returned from input() ends with a "$" before converting it to a float.
To reset when a user types something that ends with "$", you could throw an exception to break out of your calculator logic and start over. We'll surround the stuff inside your while loop with a try/catch, so that the exception doesn't stop your program, but merely starts a new iteration in the while loop.
# I omitted all your other functions at the start of the file
# but of course those should be included as well
class ResetException(Exception):
pass
#this function for input two operands.
def input_function():
s = input("Enter first number: ")
if s.endswith("$"):
raise ResetException()
number1=float(s)
s = input("Enter second number: ")
if s.endswith("$"):
raise ResetException()
number2=float(s)
global a,b
a=number1
b=number2
return a,b
#loop repeat until user need to terminate.
while True:
print("Select operation.")
print("1.Add : + ")
print("2.Subtract : - ")
print("3.Multiply : * ")
print("4.Divide : / ")
print("5.Power : ^ ")
print("6.Remainder: % ")
print("7.Terminate: # ")
print("8.Reset : $ ")
# take input from the user
try:
choice = input("Enter choice(+,-,*,/,^,%,#,$): ")
print(choice)
if(select_op(choice) == -1):
#program ends here
print("Done. Terminating")
exit()
except ResetException:
pass
def main():
num1 = input("Write a number: ")
op = input("* or / or + or -: ")
num2 = input("Write another number: ")
result = None
if op == "+":
result = float(num1) + float(num2)
print(result)
elif op == "-":
result = float(num1) - float(num2)
print(result)
elif op == "*":
result = float(num1) * float(num2)
print(result)
elif op == "/" and num2 == 0:
result = None
print("You can't divide by zero")
main()
elif op == "/" and num2 != 0:
result = float(num1) / float(num2)
print(result)
while True:
main()
ans = input("Would you like to do another equation: ")
if ans == "yes":
main()
ans = input("Would you like to do another equation: ")
elif ans == "no":
exit()
I get this error even though i already had an elif statement for that case
File "d:\Visual Studio Code\Projects\HelloWorld python\Calculator.py", line 26, in
main()
File "d:\Visual Studio Code\Projects\HelloWorld python\Calculator.py", line 21, in main
result = float(num1) / float(num2)
ZeroDivisionError: float division by zero
The reason you're not catching the zero case is that num hasn't been converted to a float. Consider using try/except instead -- that way you don't need to try to predict whether the operation will fail, you can just let the operation itself tell you. This will also let you catch things like inputs that aren't valid numbers, or operations that aren't one of the valid options.
You can also save time by doing the float conversion as soon as possible -- if you use try/except, this lets you immediately re-prompt the user for valid input. If you return the answer (and let the caller print it) rather than assigning it to a result which you then print, you can easily break the loop once the function succeeds while also making each if block a single concise line.
Note that explicitly re-calling main() isn't necessary as long as it's in a while loop that continues until it's time to break.
def main() -> float:
while True:
try:
num1 = float(input("Write a number: "))
op = input("* or / or + or -: ")
num2 = float(input("Write another number: "))
if op == "+":
return num1 + num2
elif op == "-":
return num1 - num2
elif op == "*":
return num1 * num2
elif op == "/":
return num1 / num2
else:
raise ValueError(f"Invalid operation {op}")
except ZeroDivisionError:
print("You can't divide by zero")
except ValueError as e:
print(e)
while True:
print(main())
ans = input("Would you like to do another equation: ")
if ans == "no":
break
Convert num2 to a float, either before you test it or when you test it:
### ...
elif op == "/" and float(num2) == 0.0:
result = None
print("You can't divide by zero")
main()
elif op == "/" and float(num2) != 0.0:
result = float(num1) / float(num2)
print(result)
I just want to start off by saying I know this code is wrong, I'm just testing
this is meant to be a calculator, as you may be able to see from the code I am trying to make the number they end with e.g.
10 + 10 = 20, they will keep the number 20 and can carry on with 20, I want to keep repeating that option
Code:
def add(num1, num2):
return num1 + num2
def mul(num1, num2):
return num1 * num2
def sub(num1, num2):
return num1 - num2
def div(num1, num2):
return num1 / num2
def main():
operation = input("Do you want to(+,-,*,/): ")
if(operation != "+" and operation != "-" and operation != "*" and operation != "/"):
print("That is an invalid operation")
else:
num1 = float(input("choose a number: "))
num2 = float(input("Choose another number: "))
if(operation == "+"):
answer = (add(num1, num2))
print(answer)
elif(operation == "-"):
answer = (sub(num1, num2))
print(answer)
elif(operation == "*"):
answer = (mul(num1, num2))
print(answer)
elif(operation == "/"):
answer = (div(num1, num2))
print(answer)
else:
print("Syntax error!")
def multiple(multiple):
multiple = input("would you like to carry the number(Y or N): ")
if(multiple == "Y" or multiple == "y"):
carry = input("(+,-,*,/): ")
num3 = int(input("choose a number: "))
if(carry == "+"):
print(answer + num3)
elif(carry == "-"):
print(answer - num3)
elif(carry == "*"):
print(answer * num3)
elif(carry == "/"):
print(answer / num3)
else:
print("Syntax Error!")
multiple = True
while multiple == True:
multiple()
choice = input("would you like multiple calculations? (Y or N): ")
while(choice == "y" or choice == "Y"):
main()
multiple()
multiple()
main()
error message:
line 56, in <module>
multiple()
NameError: name 'multiple' is not defined
p.s There may be some indentation errors in this as it pasted strange
You're trying to call the function multiple outside of the scope of the main function while it is only defined in it. Assuming that your indentation is as presented here, you need to move the definition of multiple outside of main so that it can be called.
Additionally, you're defining a variable named multiple which might create some problems. You should change it to something else.
I optimized your code a little and fixed it. It works fine so take a look at it.
def add(num1, num2):
return num1 + num2
def mul(num1, num2):
return num1 * num2
def sub(num1, num2):
return num1 - num2
def div(num1, num2):
return num1 / num2
def main(carry):
operation = input("Do you want to (+,-,*,/): ")
if(operation != "+" and operation != "-" and operation != "*" and operation != "/"):
print("That is an invalid operation")
else:
num1 = float(input("choose a number: "))
if carry == None:
num2 = float(input("Choose another number: "))
else:
num2 = carry
if(operation == "+"):
answer = add(num1, num2)
elif(operation == "-"):
answer = sub(num1, num2)
elif(operation == "*"):
answer = mul(num1, num2)
elif(operation == "/"):
answer = div(num1, num2)
print(answer)
return answer
if input("would you like multiple calculations? (Y or N): ") in ("y", "Y"):
domultiple = True
else:
domultiple = False
carry = None
while 1:
carry = main(carry)
if domultiple:
if input("would you like to carry the number (Y or N): ") in ("n", "N"):
break
else:
break
I am trying to build a simple calculator. I just want the user to enter two numbers and an operation, then for the calculation to be shown, then to loop back to entering two numbers again. If the user enters an operation that is not recognized I want to loop back to 'enter operation'.
Why is this not working:
def add (a,b):
return a + b
def minus (a,b):
return a - b
def multi (a,b):
return a * b
def div (a,b):
return a / b
def numPic():
num1 = int(input("Type a number: "))
num2 = int(input("Type another number: "))
def opPic():
op = input("Type an operation (add,minus,multi,div):" )
if op == "add":
print (add (num1,num2))
elif (op == "minus"):
print (minus(num1,num2))
elif (op == "multi"):
print (mulit(num1,num2))
elif (op == "div"):
print (div(num1,num2))
else :
print ("operation not recognised")
opPic ()
print ("Hello User")
numPic()
opPic()
You have a few bugs. First, num1 and num2 are local to numPic--not
global. So you need to return them to the caller, and the caller has to pass
them to opPic():
def numPic():
num1 = int(input("Type a number: "))
num2 = int(input("Type another number: "))
return num1, num2
def opPic(num1, num2):
op = input("Type an operation (add,minus,multi,div):" )
if op == "add":
print (add (num1,num2))
elif (op == "minus"):
print (minus(num1,num2))
elif (op == "multi"):
print (mulit(num1,num2))
elif (op == "div"):
print (div(num1,num2))
else :
print ("operation not recognised")
opPic (num1, num2)
num1, num2 = numPic()
opPic (num1, num2)
To make it loop-based, you could do something like:
def opPic(num1, num2):
while True:
op = input("Type an operation (add,minus,multi,div):" )
if op == "add":
print (add (num1,num2))
elif (op == "minus"):
print (minus(num1,num2))
elif (op == "multi"):
print (mulit(num1,num2))
elif (op == "div"):
print (div(num1,num2))
else :
print ("operation not recognised")
continue
break
Hopefully, you can figure out the other bit on your own, as this looks like a school assignment.
The num1 and num2 you define in numPic are local to that function. You need to return them and pass them to the opPic function for them to be used.
def numPic():
num1 = int(input("Type a number: "))
num2 = int(input("Type another number: "))
return num1, num2
def opPic(num1, num2):
#the same code as before
#except changing opPic() to opPic(num1, num2)
print ("Hello User")
num1, num2 = numPic()
opPic(num1, num2)
There are better ways of doing what you seem to be aiming for though. You haven't actually used a loop and have used recursion instead.