3

Alright, I'm doing this for a project and whenever I attempt to have it divide by zero or square root a negative number that program closes out. I've attempted to find something I can insert into the code to make it display a message and then prompt for the value again, but everything that I've tried inserting causes the program to close out instantly when I start it up.

Here's the calculator without anything inserted to fix the crashes.

import math

def convertString(str):
    try:
        returnValue = int(str)
    except ValueError:
        returnValue = float(str)
    return returnValue

def addition(a, B):
    return convertString(a) + convertString(B)

def subtraction(a, B):
    return convertString(a) - convertString(B)

def multiplication(a, B):
    return convertString(a) * convertString(B)

def division(a, B):
    return convertString(a) / convertString(B)

def sqrt(a):
    return math.sqrt(convertString(a))

keepProgramRunning = True

print "Welcome to [Removed]'s 2011 4-H Project! This is a simple calculator coded in  Python, which is a high-level programming language. Java, C, C++, and Perl are  other high-level programming languages that you may have heard of."

while keepProgramRunning:
    print ""
    print "Please choose what you would like to do:"
    print ""
    print "1) Addition"
    print "2) Subtraction"
    print "3) Multiplication"
    print "4) Division"
    print "5) Square Root"
    print "6) Quit Program"

    choice = raw_input()    

    if choice == "1":
        numberA = raw_input("Enter your first addend: ")
        numberB = raw_input("Enter your second addend: ")
        print "The sum of those numbers is:"
        print addition(numberA, numberB)
    elif choice == "2":
        numberA = raw_input("Enter your first term: ")
        numberB = raw_input("Enter your second term: ")
        print "The difference of those numbers is:"
        print subtraction(numberA, numberB)
    elif choice == "3":
        numberA = raw_input("Enter your first factor: ")
        numberB = raw_input("Enter your second factor: ")
        print "The product of those numbers is:"
        print multiplication(numberA, numberB)
    elif choice == "4":
        numberA = raw_input("Enter your dividend: ")
        numberB = raw_input("Enter your divisor: ")
        print "The quotient of those numbers is:"
        print division(numberA, numberB)
    elif choice == "5":
        numberA = raw_input("Enter the number you wish to find the square root of: ")
        print "Your result is:"
        print sqrt(numberA)
    elif choice == "6":
        print "Goodbye! Thank you for your time spent both judging my project and those of everyone else! Have a nice day! (。◕‿◕。)"
        keepProgramRunning = False
    else:
        print "Please choose a valid option."
        print "\n"

I'm not real sure what to insert and where to solve the crashes, but I think the problem lies with my placement.

I've been attempting to insert something like this:

except ValueError:
            print "You cannot divide by zero. Please choose another divisor."
            numberB = raw_input("Enter your divisor: ")

Would that work? Where would I insert it? If it wouldn't work, what would and where would it go?

I've been attempting to put it after

numberB = raw_input("Enter your divisor: ")

So that section would read

elif choice == "4":
    numberA = raw_input("Enter your dividend: ")
    numberB = raw_input("Enter your divisor: ")
        except ValueError:
            print "You cannot divide by zero. Please choose another divisor."
            numberB = raw_input("Enter your divisor: ")
    print "The quotient of those numbers is:"
    print division(numberA, numberB)

But as I said, the program will close as soon as it opens when I do try that. Also, I know that if they inputted 0 again the program would crash. Is there any way to make it return to the line that it's under?

Also, for closing the program, the message it is supposed to display can't be read as the program is closing immediately after it's displayed, or the commands are being executed at the same time. Either way, the message can't be read. Is there any way to make the message appear in a separate dialog window that will cause the program to close when the window is closed? Or at least a way to make it delay before closing?

Please correct me if I got any terminology wrong. I'm still somewhat new to this.

And, as always, (constructive) feedback for any part of the program is always appreciated.

Kara
  • 6,115
  • 16
  • 50
  • 57
Sam
  • 75
  • 2
  • 7

5 Answers5

3

The problem is that you are trying to catch an exception before it is thrown. Instead, try this:

elif choice == "4":
    numberA = raw_input("Enter your dividend: ")
    numberB = raw_input("Enter your divisor: ")
    while float(numberB) == 0:
        print "You cannot divide by zero. Please choose another divisor."
        numberB = raw_input("Enter your divisor: ")
    print "The quotient of those numbers is:"
    print division(numberA, numberB)
gereeter
  • 4,731
  • 1
  • 28
  • 28
  • 1
    In other words, you should not use exceptions; you should explicitly test whether the number is invalid. Additionally, you need to loop to keep asking for a number if the previous attempt failed. – Nayuki Jul 13 '11 at 02:00
  • I'm the OP. Thank you both for the feedback! It's very helpful. I'll post back in a moment after testing it. – Sam Jul 13 '11 at 02:02
2

Here's your answer without exception handling. Essentially you just make this questionable input at the beginning of an infinite loop, but break out when you find that the input is all good.

For your square root:

elif choice == "5":
    while True:
        numberA = raw_input("Enter the number you wish to find the square root of: ")
        if float(numberA) >= 0:
            break
        print "Cannot take the square root of a negative number."
    print "Your result is:", sqrt(numberA)

and for division:

elif choice == "4":
    numberA = raw_input("Enter your dividend: ")
    while True:
        numberB = raw_input("Enter your divisor: ")
        if numberB != "0":
            break
        print "You cannot divide by zero. Please choose another divisor."
    print "The quotient of those numbers is:", division(numberA, numberB)

And to make your program stall before it closes:

elif choice == "6":
    print "Goodbye! Thank you for your time spent both judging my project and those of everyone else! Have a nice day! (。◕‿◕。)"
    raw_input('')
    keepProgramRunning = False

Cheers!

machine yearning
  • 9,889
  • 5
  • 38
  • 51
  • OP again. I tried all the examples you gave with exceptions, but the program closes as soon as it opens regardless. I checked and double checked that the formatting was correct but it still doesn't work. Gereeter's(The first person to answer who advised against using exceptions.) method works just fine, however. I can also enter 0 as the divisor as much as I want but it keeps looping back. Thank you all for the answers however. They are all very much appreciated. Now, is there anyway to make the "Goodbye" message readable? What are my options? – Sam Jul 13 '11 at 02:14
  • Oh, additionally, is there a command that I could use for the sqrt issue? How could I make it check if the value entered is a negative number, and then make it respond similarly to how it does for when you attempt to enter a value of 0 for the divisor now that I've fixed it? – Sam Jul 13 '11 at 02:19
  • Thank you for the advice on how to stall it when it closes. It works fantastically. However, the exceptions still cause the program to close when it opens up, no matter what I do. – Sam Jul 13 '11 at 02:32
  • It's fine, I'm sure it's just an issue on my end or something else that I did. Your response was still very informative and helpful. Would you know how I could resolve the sqrt issue, by chance? – Sam Jul 13 '11 at 02:45
  • I know it is, but that's the exception method that doesn't work for whatever reason. >. – Sam Jul 13 '11 at 02:58
  • @Sam: Here you go, I took out all the exception stuff. Better? – machine yearning Jul 13 '11 at 03:12
  • Much better! Thank you so much! – Sam Jul 13 '11 at 03:17
1

You should use exceptions, like you're already doing in convertString.

try:
    result = division(numberA, numberB)
    print "The quotient of those numbers is:"
    print result
except ZeroDivisionError:
    print "You cannot divide by zero. Please choose another divisor."
MRAB
  • 20,356
  • 6
  • 40
  • 33
0

Your format of the try:...except: statement is wrong. Try this:

elif choice == "4":
    numberA = raw_input("Enter your dividend: ")
    numberB = raw_input("Enter your divisor: ")
    print "The quotient of those numbers is:"
    try:
        print division(numberA, numberB)
    except ZeroDivisionError:
        print "You cannot divide by zero. Please choose another divisor."
TorelTwiddler
  • 5,996
  • 2
  • 32
  • 39
0

This does not answer your coding question, but I think it is worth to comment.

sqrt: The square root of a negative number is an imaginary number. Python supports complex numbers with complex(real_part, imaginary_part).

so your sqrt calculation could be written as:

elif choice == "5":
    numberA = raw_input("Enter the number you wish to find the square root of: ")
    numberA = float(numberA)
    if numberA < 0:
        sqrt_numberA = complex(0, sqrt(abs(numberA)))
    else:
        sqrt_numberA = sqrt(numberA)

    print "Your result is:", sqrt_numberA

division: A division by 0 is infinite. Python indicates infinite with 'inf'. In fact, it returns 'inf' with numbers higher than 1E309:

>>> 1E309
inf

and the division of two of these numbers produces 'nan'

>>> 1E309/1E309
nan

so that you could write:

elif choice == "4":
    numberA = raw_input("Enter your dividend: ")
    numberB = raw_input("Enter your divisor: ")
    try: 
        div = division(numberA, numberB)
    except ZeroDivisionError:
        div = 'inf'

    print "The quotient of those numbers is:", div

this code should be additionally extended to return -inf, when numberA is negative, and to take into account situations such as 0/0

joaquin
  • 82,968
  • 29
  • 138
  • 152