# Introduction to Loops¶

In [22]:
import numpy as np


## Problem 1¶

Write code to print the numbers 0 to 4 on each line below.

### Solution¶

In [53]:
print(0)
print(1)
print(2)
print(3)
print(4)

0
1
2
3
4


### Discussion¶

• Okay, let's keep going to 10000...(!?)

## Loops¶

• Loops in programing are used to simplify repetative work.
• Above, each line is a print statement.
• The only thing different on each line is the number we are printing.
• We can write a loop statment to do the above problem as follows
In [54]:
for i in range(10):
print(i)

0
1
2
3
4
5
6
7
8
9


### Discussion¶

• What are the parts of this: list them?
• i can be any variable, not just "i"
• Is there anything weird or unexpected here?

## Problem 2¶

• We can put any code in the for loop
• Variables, functions, expressions, math, etc.
• We can put variables outside of the loop that are available inside of the loop

For the ideal gas law, pressure is given by $$P = nRT/V$$

• n = 1 kmol
• R = 8314 J/kmol*K
• T = 300 K

For V = 2, 3, 4, 5, ... 20, use a loop to find and print the values of P for each V.

### Solution¶

In [1]:
n = 1
R = 8314
T = 300

for V in range(2,21):
P = n*R*T/V
print(P)

1247100.0
831400.0
623550.0
498840.0
415700.0
356314.28571428574
311775.0
277133.3333333333
249420.0
226745.45454545456
207850.0
191861.53846153847
178157.14285714287
166280.0
155887.5
146717.64705882352
138566.66666666666
131273.68421052632
124710.0


### Discussion¶

• What if you wanted V to not step by integers?
• Step by 2? Step by 5?
• Step by 0.2?

## Problem 3¶

Add all the numbers from 0 to 100

• Before you start the code, think about what you would do if solving this in your head?
• How do you start?
• What things do you keep track of?
• What variables to use?
• What is the loop syntax?
• How do variables interact with the loop?
• Think through the process of the problem to the solution

### Solution¶

In [9]:
s = 0
for i in range(101):
s = s + i
print(s)

5050


## Nested loops¶

• We can put any code in a for loop. Even another loop.
• Look at the code below.
• Before running it, think of what you expect to see.
• Now run it and compare. Did you get what you thought you would?
for i in range(3):
print(f"i={i}")
for j in range(4):
print(f"  j={j}")

In [4]:
for i in range(3):
print(f"i={i}")
for j in range(4):
print(f"  j={j}")

i=0
j=0
j=1
j=2
j=3
i=1
j=0
j=1
j=2
j=3
i=2
j=0
j=1
j=2
j=3

• Note, each time through the top (outer) loop, everything inside is done.
• This means the whole inner loop is computed for each outer loop.
• Think of an actual application for a nested loop.

## Problem 4a¶

• Given the following function $$f(x) = x^2 - 3,$$ we can use Newton's method to find $x$ for $f(x)=0$.

• Recall, Newton recurrence formula: $$x_{new} = x_{old} - \frac{f(x_{old})}{f^\prime(x_{old})}$$

### We solved this previously in Excel¶

• Open Excel and solve this problem.
• Think about the steps involved, how we set it up.
• Use the simplest method possible.

### Solution-Excel*¶

Excel Python
cell for guess ??
Newton equation in terms of x cell
A2 - (A2^2-3)/(2*A2)
??
repeat: fill down ??

## Problem 4b¶

### Now solve in Python using loops¶

• Try to write the simplest solution you can think of with as few lines of code as possible.
• We want 3 decimal places of accuracy.
• Consider:
• What variables are needed?
• How to setup and use the loop.
• What to print and where?

### Solution-Python¶

In [5]:
x = 1
for i in range(6):
x = x - (x**2 - 3)/(2*x)
print(x)

2.0
1.75
1.7321428571428572
1.7320508100147276
1.7320508075688772
1.7320508075688774


### Discussion¶

• Variable i is not being used, it is just for convenience in creating the loop.
• Note how x is used on both sides of the equation. It is reused.

### Explicitly write out the four steps¶

• We don't have to code it from top to bottom...
• Compare to Excel
Excel Python
cell for guess variable for x
Newton equation in terms of x cell
A2 - (A2^2-3)/(2*A2)
Newton equation in terms of x
x = x - (x**2-3)/(2*x)
repeat: fill down repeat: wrap in loop
In [6]:
# step 1: initial guess
x = 1

# step 2: add Newton equation
x=1
x = x - (x**2 - 3)/(2*x)

# step 3: wrap in loop
x=1
for i in range(6):
x = x - (x**2 - 3)/(2*x)

# step 4: add a print
x=1
for i in range(6):
x = x - (x**2 - 3)/(2*x)
print(x)

2.0
1.75
1.7321428571428572
1.7320508100147276
1.7320508075688772
1.7320508075688774


## Problem 4c¶

Redo Solution 1 using functions for $f(x)$ and $f^\prime(x)$.

• Recall: we discussed functions two classes back.
In [7]:
def f(x):
return x**2 - 3

def fprime(x):
return 2*x

x = 1

for i in range(6):
x = x - f(x)/fprime(x)
print(f"after iteration {i+1}, x={x:.4f}")

after iteration 1, x=2.0000
after iteration 2, x=1.7500
after iteration 3, x=1.7321
after iteration 4, x=1.7321
after iteration 5, x=1.7321
after iteration 6, x=1.7321


## Problem 4d¶

• Now, to get to three decimal places we only needed 3 iterations.
• But we didn't know this at the beginning, so we guessed 6.
• If 6 wasn't enough, we would do more.
• This guess and check is not very efficient.

Modify the code above to do just the right number of iterations.

• What Python features do you need to use?
• How do you decide when you are done?

### Solution¶

In [8]:
def f(x):
return x**2 - 3

def fprime(x):
return 2*x

xold = 1

for i in range(6):
xnew = xold - f(xold)/fprime(xold)
err = np.abs( (xnew-xold) / xnew )
if np.abs(err < 1E-3):
break
print(f"after iteration {i+1}, x={xnew:.4f}")
xold = xnew

after iteration 1, x=2.0000
after iteration 2, x=1.7500
after iteration 3, x=1.7321


### Discussion¶

• Keep track of old and new x: xold and xnew.
• Need to reset xold=xnew at the end to get set for next interation.
• New keyword
break

• Define the error and compare it to the desired accuracy.
• Use absolute value: np.abs()
In [ ]: