1

I have a function below, that takes a value as an input, and determines a new_value (the new_value will always be less than the original_value). If the difference between the new_value and the original_value is less than a specified tolerance, the new_value is returned. If the tolerance is greater, the function is called again with the new_value as the argument, to calculate a new_new_value. Depending on the original_value entered, sometimes the tolerance condition is never met. How can I make the function stop iterating after a certain number of iterations? I have tried to put in count=0, the count+=0 after the else, but that doesn't work as it returns to zero each time the function is called again. Thanks

def calc_value(original_value):
   # equations to calculate new_value
   if original_value - new_value < tolerance:
      return new_value
   else calc_value(new_value)
vks
  • 67,027
  • 10
  • 91
  • 124
Anna
  • 29
  • 4
  • This depends specifically on what you're doing in the part you've commented out. – jfaccioni Apr 22 '20 at 20:14
  • @jfaccioni how come? Is there some way that I can count the number of times that the function calc_value is called, and after a certain number of times return a new_value? – Anna Apr 22 '20 at 20:17
  • @Anna you sort of need `static vairables`.See my answer – vks Apr 22 '20 at 20:19

3 Answers3

0

You shouldn't be using recursion for this. Use a for loop to iterate a fixed number of times, using the tolerance test to break early where appropriate.

def calc_value(original_value):
    old_value = original_value
    for _ in range(10):
        new_value = ...
        if abs(old_value - new_value) < tolerance:
            break
        old_value = new_value
    return new_value
chepner
  • 497,756
  • 71
  • 530
  • 681
  • This is an infinate loop, don't forget to `i += 1` in the while loop – GTBebbo Apr 22 '20 at 20:18
  • 1
    Switched to a `for` loop instead; given the way I structured the loop, I wasn't using doing the tolerance test in the loop condition anyway. – chepner Apr 22 '20 at 20:37
0

If you want to stop iterating after you reach a certain iteration depth you will need to pass a counter into the function. This can be done with a default argument in the function:

def calc_value(original_value, count = 0):
   # equations to calculate new_value
   if original_value - new_value < tolerance:
      return new_value
   else:
      if count > 100:
          return new_value  # Handle reaching limit
      calc_value(new_value, count + 1)

Every time you call the function reccursively, add 1 to the count and check if the limit has been reached.

By using a default argument, you don't need to bother setting it when you call the function:

calc_value(42)

You could even take this further and add a limit argument to specify the iteration limit:

def calc_value(original_value, count = 0, limit = 100):
    # ...
    if count > limit:
        return new_value
    calc_value(new_value, count, limit)

Then you can define the arguments either by order, or by specifying the argument:

# Default values: count = 0, limit = 100
calc_value(42)

# Will set count to default 0, and limit to 150
calc_value(42, limit=150)

# Will set count to 5, and limit to 200
calc_value(42, 5, 200)

# Will set count to 5, and limit to 150
calc_value(42, limit=150, count=5)
GTBebbo
  • 1,198
  • 1
  • 8
  • 17
0

You can use function attributes. Something like this.

def fun(x):
    if fun.counter<=max_value:
        fun.counter+=1
    else:
        return
    print x
    if x:
        fun(x-1)
fun.counter = 0
max_value = 3
fun(5)
vks
  • 67,027
  • 10
  • 91
  • 124
  • I've never seen these before, so these are the same as static variables in c? Is there a way to initialize them within the function like in C? – GTBebbo Apr 22 '20 at 20:37
  • 1
    @GTBebbo not exactly same but yes can be used as such – vks Apr 22 '20 at 20:38