Python Forum

Full Version: ZeroDivisionError help
You're currently viewing a stripped down version of our content. View the full version with proper formatting.
Pages: 1 2
I have spent way to much time on this. What I need to do, make a math tutor. I have this entire thing figured out but this.

What it needs to do, if a zero is input, I need it to read an error and then loop ONLY to the division...not back to the main menu.

Please tell me there is someone who can help. I have tried so many things for the last three days and my eyes are going cross.

#division calculation
        elif choice == divF:
            try:
                num1 = int(input("Enter first number: "))
                num2 = int(input("Enter second number: "))

                c_answer = (num1 / num2)

            except ZeroDivisionError:
                print("Cannot use a zero in division, please try again")

            answer = float(input("Enter answer:"))

#output
            if c_answer == answer:
                print("Correct, great job!")
            else:
                print(f'Incorrect, the answer is {c_answer:.2f} .')
 

This currently will ask for first and second number, then show the error....but then asks for answer (which is obviously going to work)...then it shows the error. If a zero is input in the first two numbers, then an error needs to show, then loop back to ask for the numbers again until no zeros are input. Then it continues with the program.

**be kind, this is my first post in any group...and this is my first programing class ever.**
If an exception was raised in your try block, all remaining code will be ignored and execution jumps to the except block. From what I can see from your code, your output code should be inside your try block. Because when no exception was raised it should run that code. If an exception was raised you can handle that within the except block.
#division calculation
        elif choice == divF:
            try:
                num1 = int(input("Enter first number: "))
                num2 = int(input("Enter second number: "))                

                if num1 != 0 and num2 != 0:
                    answer = float(input("Enter answer:"))

                    c_answer = (num1 / num2)

                    if c_answer == answer:
                        print("Correct, great job!")
                    else:
                        print(f'Incorrect, the answer is {c_answer:.2f} .')
                else:
                    print("Cannot divide with zero, try again.")          

            except ZeroDivisionError:
                print ('Error')
I actually just changed it to this...I am just trying so many things and learning as I go (even though I am taking this as a class).
so after the else...it needs to go back to the num1 and num2.
It is difficult to give a proper suggestion if I can't see the rest of the code. I'm assuming your code runs in a loop? If so, I think my suggestion would still work, since it will repeat the input section again.

If not, it would be a matter of overall design of your program. There would different ways to ask for input again after an exception.
(Jun-18-2024, 07:30 PM)Jeff_900 Wrote: [ -> ]It is difficult to give a proper suggestion if I can't see the rest of the code. I'm assuming your code runs in a loop? If so, I think my suggestion would still work, since it will repeat the input section again.

If not, it would be a matter of overall design of your program. There would different ways to ask for input again after an exception.

Yes, it runs on a loop unless you choose quite. The issue is, the assignment says to have it ask the questions again and not bring up the menu choices. That is where I am having an issue. The second one I posted...if you put a zero it bring me back to the main menu, but I want it to bring me to the num1 and num2 and not leave the div until the problem is solved.
(Jun-18-2024, 07:30 PM)Jeff_900 Wrote: [ -> ]It is difficult to give a proper suggestion if I can't see the rest of the code. I'm assuming your code runs in a loop? If so, I think my suggestion would still work, since it will repeat the input section again.

If not, it would be a matter of overall design of your program. There would different ways to ask for input again after an exception.

Yes, it runs on a loop unless you choose quite. The issue is, the assignment says to have it ask the questions again and not bring up the menu choices. That is where I am having an issue. The second one I posted...if you put a zero it bring me back to the main menu, but I want it to bring me to the num1 and num2 and not leave the div until the problem is solved.


Here is what it looks like when I run it...after the error, I need it to ask the num1 and num2 questions
[attachment=2917]
Not necessarily the only answer. I think there would be more elegant ways to solve the problem but this while loop will do the trick in your case.

# assume an error
    error = True
    # while there is an error, repeat over and over again
    while error == True:
        try:
            num1 = int(input('Enter first number: '))
            num2 = int(input('Enter second number: '))
            c_answer = (num1 / num2)
            # change error to False, while loop stops
            error = False

        except ZeroDivisionError as e:
            print(dir(e))
            # in this case a bit redundant (error already assumed), but error remains True on exceptions
            error = True
I think the way to do this is remove input validation from the test and put it in a special function that only does input. Something like this:
def input_number(prompt, tests=None):
    """Get integer input.  Verify input passes all tests."""
    while True:
        try:
            value = int(input(prompt))
            if tests is None or all(test(value) for test in tests):
                return value
        except ValueError:
            pass


a = input_number("Enter an integer : ")
b = input_number("Enter a non-zero integer : ", (lambda x: x != 0,))
print(f"{a} / {b} = {a / b}")

a = input_number("Enter an even integer > 8 : ", (lambda x: x % 2 == 0, lambda x: x > 8))
b = input_number("Enter an odd integer : ", (lambda x: x % 2 != 0,))
print(f"{a} * {b} = {a * b}")
If you enter a number like 060 that is no problem for the int() function:

num = '060'
int(num) # returns 60
In any division, it is OK if the dividend is zero, so we do not need to check num1 at all.

In any division, the divisor should not be zero, because mathematicians say, this division is "undefined". I disagree with that formulation, but that is another matter.

The string 0 (zero) starts with zero, so to save trouble, and because we do not normally write leading zeroes, we will just reject any input string for num2 which begins with zero:

import re

e = re.compile('0')
f = re.compile(r'\D')
# keep asking for numbers until the divisor does not start with zero
# only integers allowed
def do_division():
    while True:
        print('Attention attention!')
        print('Only integers allowed, no other characters.')
        print('The first integer can be zero, the second integer camnnot start with zero!')
        nums = input('Enter your 2 integers, separated by a space ... ').split()
        # check for any non-number characters
        if f.search(nums[0]) or f.search(nums[1]):
            print('Only integers allowed, no other characters, try again ... ')
        # check for 0 at the start of the string
        elif e.match(nums[1]):
            print('The divisor cannot start with zero, try again ...')
        # if the above are good get the result    
        else:
            result = int(nums[0]) / int(nums[1])
            print(f'{int(nums[0])} / {int(nums[1])} = {result}')
            break
    return result
e.match(nums[1]) looks to see if nums[1] begins with zero. (Zero also begins with zero.)

f.search(n) looks to see if nums[0] or nums[1] contain any characters that are not numbers (that's the \D)

If e and f both return None, the division can go ahead.

Thinking about what to do with floats, I think the whole thing is better like this, for floats or integers:

import re

# find a float or integer
# find a float
g = re.compile(r'\A(?=\d+(.\d+)?\Z).*')
# use h to look for at least 1 number between 1 and 9 in the divisor
# otherwise, there are just zeroes
h = re.compile(r'[1-9]+')
def do_division():
    while True:
        print('Attention attention!')
        print('Only integers or floats allowed: number or number.number, no other characters.')
        nums = input('Enter your numbers, separated by a space ... ').split()        
        if not h.search(nums[1]):
            print('And the second number must contain at least 1 number > 0 ... ')
            continue        
        # check for any non-number characters
        elif g.match(nums[0]) and g.match(nums[1]):
            result = float(nums[0]) / float(nums[1])
            print(f'{nums[0]} / {nums[1]} = {result}')
            break
        else:
            print('The numbers you entered do not have the correct format, try again ... ') 
    return result
\A the start or the string
\d+ one or more digits
(.\d+)? optionally followed by .digit(s) like .2345
\Z end of string

Anything else will not return a match.
Solved it...

#division calculation
        elif choice == divF:
            while (num1 := int(input('Enter first number: '))) == 0:
                print ('Number must not be a zero.')
                    
            while (num2 := int(input("Enter second number: "))) == 0:
                print ('Number must not be a zero.')

            answer = float(input("Enter answer (to 2 decimal points): "))

            c_answer = float(num1 / num2)
#output
            if c_answer == answer:
                print("Correct, great job!")
            else:
                print("Incorrect, the answer is ", f'{c_answer:.2f}',".")
And it works perfectly :) it loops back to the question until a number other than zero is entered.
Pages: 1 2