8

In the code below, I'd like the while loop to exit as soon as a + b + c = 1000. However, testing with print statements shows that it just continues until the for loops are done. I've tried while True and then in the if statement set False but that results in an infinite loop. I thought using x = 0 and then setting x = 1 might work but that too just runs until the for loops finish. What is the most graceful and fastest way to exit? Thanks.

a = 3
b = 4
c = 5
x = 0
while x != 1:
    for a in range(3,500):
        for b in range(a+1,500):
            c = (a**2 + b**2)**0.5
            if a + b + c == 1000:
                print a, b, c
                print a*b*c
                x = 1
erdekhayser
  • 6,537
  • 2
  • 37
  • 69
caadrider
  • 93
  • 1
  • 1
  • 5
  • 3
    ignoring the loop issue... you're going to have floating point issues here... specifically, c is a floating point # and so you're going to want to either: round it, cast it, or check if abs(a+b+c-1000) < 0.00001 (or some other epsilon). Or I could be totally mistaken. – Foon May 20 '13 at 18:58
  • `c` is floating, but it didn't seem to matter. The program finds an `a+b+c=1000` so apparently doesn't care about `1000` vs `1000.0`. Good to know though because it could be an issue at times. – caadrider May 21 '13 at 21:28

6 Answers6

9

The while loop will match the condition only when the control returns back to it, i.e when the for loops are executed completely. So, that's why your program doesn't exits immediately even though the condition was met.

But, in case the condition was not met for any values of a,b,c then your code will end up in an infinite loop.

You should use a function here as the return statement will do what you're asking for.

def func(a,b,c):
    for a in range(3,500):
        for b in range(a+1,500):
            c = (a**2 + b**2)**0.5
            if a + b + c == 1000:
                print a, b, c
                print a*b*c
                return # causes your function to exit, and return a value to caller

func(3,4,5)

Apart from @Sukrit Kalra's answer, where he used exit flags you can also use sys.exit() if your program doesn't have any code after that code block.

import sys
a = 3
b = 4
c = 5
for a in range(3,500):
    for b in range(a+1,500):
        c = (a**2 + b**2)**0.5
        if a + b + c == 1000:
            print a, b, c
            print a*b*c
            sys.exit()     #stops the script

help on sys.exit:

>>> print sys.exit.__doc__
exit([status])

Exit the interpreter by raising SystemExit(status).
If the status is omitted or None, it defaults to zero (i.e., success).
If the status is numeric, it will be used as the system exit status.
If it is another kind of object, it will be printed and the system
exit status will be one (i.e., failure).
Community
  • 1
  • 1
Ashwini Chaudhary
  • 244,495
  • 58
  • 464
  • 504
  • Thank you. If I use a function I don't really need the `while` loop at all. As I understand, the function would run until the condition to `return` is met and then it would exit. That works fine, but doesn't really help me understand why my original `while` loop won't exit. – caadrider May 20 '13 at 19:00
  • It exits. It just does some extra `for` loops. – Sukrit Kalra May 20 '13 at 19:01
  • your code will stop executing when the `for` loops are finished. In the OP's post, however, if the `if` condition was not met in any case, the loops will start over from the beginning. – pascalhein May 20 '13 at 19:11
  • That's the issue, I'd like it to exit without doing the extra `for` loops. Basically, I'm trying to figure out how to make a `while` loop exit early once a condition is met. Doing it outside a function doesn't seem to work. Maybe I should be using functions more, but seems like it should work. – caadrider May 20 '13 at 19:13
  • @caadrider then why did you use a `while` loop? – pascalhein May 20 '13 at 19:14
  • Since the same things are being done in the `while` loop everytime, wouldn't it actually be better to just exit if the condition is not satisfied in the first time, since it never will be satisfied? – Sukrit Kalra May 20 '13 at 19:14
  • @csharpler - I used the `while` loop because I don't know when the condition will be met but I do know it will eventually and before `a=500` so for efficiency I just want to end asap and not keep running. Is there a better way to do it that I'm not seeing? – caadrider May 20 '13 at 19:17
  • You could have broken out of the innermost loop using `break` and set a flag value which you would check in the outer loop and `break` that loop as well as soon as that flag is set to true. (Similar to the implementation of other answers) – Sukrit Kalra May 20 '13 at 19:21
5

If you don't want to make a function ( which you should and refer to Ashwini's answer in that case), here is an alternate implementation.

>>> x = True
>>> for a in range(3,500):
        for b in range(a+1, 500):
            c = (a**2 + b**2)**0.5
            if a + b + c == 1000:
                 print a, b, c
                 print a*b*c
                 x = False
                 break
         if x == False:
            break
200 375 425.0
31875000.0
Sukrit Kalra
  • 33,167
  • 7
  • 69
  • 71
  • That works. I wish there was a way to break out of nested loops in one fell swoop. I thought the `while` loop would provide that option but so far I can't figure out how to make it work. – caadrider May 20 '13 at 19:25
  • You won't be able to swiftly break out of all the nested loops. If you're in a script however, you can use `sys.exit()` which will break out of the complete execution of the file and execute nothing after it. – Sukrit Kalra May 20 '13 at 19:29
  • 1
    @caadrider Python doesn't have a `goto` statement like `C`, so you can't just jump out of nested loops suddenly. So a good option here is to use functions. – Ashwini Chaudhary May 20 '13 at 19:31
  • @Ashwini - thanks for the clarification. Looks like functions are the best way to do this. Time to embrace them. :) – caadrider May 20 '13 at 19:35
  • This [PEP](http://www.python.org/dev/peps/pep-3136/#motivation) might be a useful read. – Sukrit Kalra May 20 '13 at 19:46
  • Thanks for the link. Looks useful and educational. – caadrider May 21 '13 at 21:23
1

You can refactor the inner code into a function and use return to exit:

def inner():
    for a in range(3,500):
        for b in range(a+1,500):
            c = (a**2 + b**2)**0.5
            if a + b + c == 1000:
                print a, b, c
                print a*b*c
                return False
    return True

while inner():
    pass

Have a look at this question.

Community
  • 1
  • 1
pascalhein
  • 5,700
  • 4
  • 31
  • 44
1

The problem is, even though you set x=1 when a+b+c==1000, you do not break out of the two for loops when that condition is met, and so the while loop doesn't know that x==1 until both for loops finish. To avoid this problem, you can add explicit break statements to the for loops (and as Sukrit Kalra points out, the while loop becomes unnecessary).

a = 3
b = 4
c = 5
x = 0
for a in range(3,500):
  for b in range(a+1,500):
     c = (a**2 + b**2)**0.5
     if a + b + c == 1000:
        print a, b, c
        print a*b*c
        x = 1
        break
  if x==1:
     break
David Ding
  • 201
  • 2
  • 3
1

You could use a break statement:

a = 3
b = 4
c = 5
x = 0
while x != 1:
    for a in range(3,500):
        for b in range(a+1,500):
            c = (a**2 + b**2)**0.5
            if a + b + c == 1000:
                print a, b, c
                print a*b*c
                break
TyCharm
  • 325
  • 1
  • 2
  • 16
0

You can wrap with try/excep and raise when the condition is met.

class FinitoException(Exception):
    pass

a = 3
b = 4
c = 5
x = 0
try:
  for a in range(3,500):
      for b in range(a+1,500):
          c = (a**2 + b**2)**0.5
          if a + b + c == 1000:
              print a, b, c
              print a*b*c
              raise FinitoException()
except FinitoException:
    return # or whatever
Israel Unterman
  • 13,158
  • 4
  • 28
  • 35
  • I'll have to wait until my Python gets a lot better for this one. Thanks for the tip though. I'll look into `try` statements. Haven't learned those yet. – caadrider May 20 '13 at 19:21