Question

I am currently writing a program that will solve the pythagorean theorem. However, I have a bug in the program. Whenever I put in a negative number for length a or b, it prints out "A cannot be less than zero" but goes ahead and solves for C anyway and prints out the length of C even though the user hasn't input b yet. How can I make it so when the user inputs a negative number it prints out the statement "A cannot be less than zero" and then loops again to inputting a length for the side, instead of how it is now where after it prints out the statement it redirects to the end?

Here is my code:

 import math
    print"This program will solve the pythagorean theorem for you"
    unit=raw_input('Enter the unit you will be using')
    a=float(raw_input('Enter the length of side a'))
    if a<=0:
      print"A cannot be less than zero"
    else:
        b=float(raw_input('Enter the length of side b'))
    if b<=0:
      print"B cannot be less than zero"
    else:
        c2=(a**2)+(b**2)
        c=math.sqrt(c2)
        c=str(c)
        print "The length of side C is: "+ c + " " + unit + "."
Was it helpful?

Solution 2

Well to begin with, if you want to constantly check your inputs, you are going to have to use a loop. As in, the psuedocode for the algorithm should be:

Loop Begin
Check the value of a and b
If a or b is less than 0 then ask for input again
Otherwise, continue

Please note, that the algorithm has to run at least once.

That is basically how the psuedocode should look like. So, this is a case where you can use a do-while loop construct. In Python, there isn't something like this, so we emulate it:

import math


def take_in():
    a = raw_input("Enter the value of side a -> ")
    b = raw_input("Enter the value of side b -> ")

    # Trying to convert to a float
    try:
        a, b = float(a), float(b)
        # If successfully converted, then we return
        if a > 0 and b > 0:
            return a, b
    except ValueError:
        pass
    # If we cannot return, then we return false, with a nice comment

    print "Invalid input"
    return False


def main():
    # Calling the function at least once
    valid = take_in()

    # While we are not getting valid input, we keep calling the function
    while not valid:
        # Assigning the value to valid
        valid = take_in()

    # Breaking the return tuple into a and b
    a, b = valid
    print math.sqrt(a ** 2 + b ** 2)


if __name__ == '__main__':
    main()

OTHER TIPS

You missed one indentatino level. Try it like this :

if a<0:
  print"A cannot be less than zero"
else:
    b=raw_input('Enter the length of side b')
    b=float(b)
    if b<0:
        print"B cannot be less than zero"
    else:
        c2=(a**2)+(b**2)
        c=math.sqrt(c2)
        c=str(c)
        print "The length of side C is: "+ c + " " + unit + "."

Try to avoid using nested if when designing the program flow. It leads to this kind of bug (missing one level of indentation). Big chunks of code inside if blocks and many nested if blocks make the program harder to follow and reason about.

Instead, you can ask again until the input is valid:

a = -1
while a < 0:
    try:
        a=float(raw_input('Enter the length of side a'))
    except ValueError:
        pass
    if a<0:
        print "A cannot be less than zero"

Fred's advice is good, wrap it into a function for reuse:

def validate(initial, prompt, test, message, typecast=str):
    value = initial
    while not test(value):
        try:
            value = typecast(raw_input(prompt))
        except ValueError:
            print "Invalid value"
            continue

        if not test(value):
            print message
            continue

        return value

Then use:

a = validate(
    initial = -1, 
    prompt = 'Enter the length of side A', 
    test = lambda x: x >= 0,
    message = "A cannot be less than zero",
    typecast = float
)
b = validate(
    initial = -1, 
    prompt = 'Enter the length of side B', 
    test = lambda x: x >= 0,
    message = "B cannot be less than zero",
    typecast = float,
)

disclaimer: I'm using a different version of Python so mileage may vary

import math

a = 0
b = 0

def py_theorem(a, b):
    return(a**2 + b**2)


unit = raw_input('Enter the unit you will be using: ')

while a <= 0:
a = float(raw_input('Enter the length of side A: '))
if a <= 0:
    print('A cannot be less than 0.')

while b <= 0:
b = float(raw_input('Enter the length of side B: '))
if b <= 0:
    print('B cannot be less than 0.')

print('The length of the 3rd side C is %d %s') % (py_theorem(a,b), unit)

Now if you look at my code a,b are 0 initially so you can execute the while loops (otherwise you get an error, the interpreter doesn't know about a,b up to that point). Then it repeats the statements asking for a,b respectively until you get valid input (valid in a generic sense, we do no error checking, what happens if you use a string?? >.<) Now the print is a little funky, I'd definitely look into the Python docs and see what %d %s etc are. Then we pass the return of the method (see the def py_theorem up top) to the string along with a unit. Note that the function takes two arguments a,b respectively.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top