Be sure to do all exercises and run all completed code cells.
If anything goes wrong, restart the kernel (in the menubar, select Kernel\(\rightarrow\)Restart).
Conditionals and While Loops¶
Remember to run all the examples and experiment as you go through these materials.
Conditionals¶
A conditional executes a block of code depending on whether something is true or false.
A simple example (which will be explained more clearly shortly) follows:
if 10 > 5: print("It's true!")
Copy the above code to the block below but make the statement false:
# YOUR CODE HERE
Result: [nothing should happen!]
Indentation of Code Blocks¶
Conditional blocks can be indented in the same way as function code blocks, following a colon.
The code block ends when the indentation returns to the previous level.
The code run if the condition is true must be indented by the same number of spaces.
This tells Python what is part of the block and what is outside it.
if 10 > 5:
print("Guess What?")
print("It's true!")
print("This is outside the conditional code block")
if 10 > 15:
print("Guess What?")
print("It's true!")
print("This is outside the conditional code block")
Comparisons¶
The operators <
, <=
, >
, >=
, !=
, ==
can be used for Comparisons, and can be seen as asking Python a question:
<
means “is it less than?”<=
means “is it less than or equal to?”>
means “is it greater than?”>=
means “is it greater than or equal to?”!=
means “is it not equal to?”==
means “is it exactly equal to?” (the same as)
Note that, since the equals sign is reserved for assigning values to
variables we use a double equals ==
to test exact equality.
If the condition is satisfied then Python gives a value of
True
as the answer, and if not False
.
print(10 < 5)
print(2 < 5 < 10)
print(10 == 10)
print(10 != 10)
Try different examples below to see what happens.
# YOUR CODE HERE
or
& and
¶
These so-called “boolean operators” can be chained
together, using the keywords or
, and
, as follows.
It is often a good idea to use brackets to make things work in a clear way.
(2 < 5) and (10 < 20)
Both conditions must be True
for and
to give a True
answer.
print(2<10, 50>100)
(2 < 10) and (50 > 100)
The or
operator requires only one condition to be True
(2 < 10) or (50 > 100)
More complicated expressions are allowed, but get quickly hard to follow if brackets are not used.
Operator Precedence¶
The following table shows which are evaluated first (like the BODMAS rules for algebra).
Operator |
Description |
---|---|
|
Boolean OR |
|
Boolean AND |
|
Boolean NOT |
|
Comparisons |
|
Addition and subtraction |
|
Multiplication, division, remainder |
|
Exponentiation |
If-Else Statement¶
An If-Else statement looks at a condition and continues into the next indented block if the statement is true.
a = 2
if a > 5:
print("a is greater than 5")
else:
print("a is 5 or less")
Change the value of
a
and observe the result.
#a=2
# YOUR CODE HERE
if a > 5:
print("a is greater than 5")
else:
print("a is 5 or less")
If-Elseif-Else¶
In case we have two or more conditions to test, we can use a “nested” if statement.
x = 4
if x > 0:
print("Positive")
else:
if x < 0:
print("Negative")
else:
print("Zero")
Notice how the indentation is used for putting one condition inside another
we just use another 4 spaces to indicate what is inside the second condition.
Change the value of
x
to investigate its behaviour
import math
#x = 4
# YOUR CODE HERE
if x > 0:
print("Positive")
else:
if x < 0:
print("Negative")
else:
print("Zero")
Since this is quite a common pattern, there is a special syntax using
the elif
keyword. This syntax also avoids the extra indentation.
x = -4
if x > 0:
print("Positive")
elif x < 0:
print("Negative")
else:
print("Zero")
The following exercise demonstrates the use of several elif
tests.
Conditional to give the following mapping of x values to y values: \( \begin{array} ~y = -4 & \text{if } x<-4 \\ y = \dfrac{(x+4)^2}{4} - 4 & \text{if } -4 \leq x < 0 \\ y = 4 - \dfrac{(x-4)^2}{4} & \text{if } 0 \leq x < 4 \\ y = 4 & \text{if } x \geq 4 \\ \end{array}\)
x = 3
if x < -4:
y = -4.0
#elif ???:
# YOUR CODE HERE
y = (x + 4)**2/4.0 - 4.0
#elif ???:
# y = ???
# YOUR CODE HERE
#else:
# ???
# YOUR CODE HERE
print(x, y)
Result: 3 3.75
Each elif
condition only gets tested if the previous conditions were false.
Using only If¶
It is possible to use an if statement without an else part, but be careful.
It is important to make sure all cases are covered.
Consider the following example:
x=0
if x > 0:
sign = "Positive!"
if x < 0:
sign = "Negative!"
print(sign)
Even though this looks correct, the case x == 0
is not covered, can lead to an error.
Correct the code in the next cell to correct the error before moving on
x=0
if x > 0:
sign = "Positive!"
if x < 0:
sign = "Negative!"
# YOUR CODE HERE
print(sign)
Comparing Strings¶
Strings can also be compared, as illustrated below:
print("hello" == "Hello")
print("hello" == "hello")
print("a" < "b")
print("A" > "a")
print("100" > "a")
Notice that the strings have to be identical (including capitalisation) to be equal.
Also the comparison of less than or greater than refers to their alphanumeric order,
where numbers come before letters, and uppercase before lowercase.
Therefore to compare strings we could write the following code:
s1 = "Aardvark"
s2 = "aardvark"
if s1 < s2:
print(s1, "comes before", s2, "in the dictionary.")
elif s1 > s2:
print(s2, "comes before", s1, "in the dictionary.")
else:
print(s1, "and", s2, "are the same!")
Iteration Using While Loops¶
Iteration¶
Sometimes you will need to repeat the same step over and over,
using the results from one step as the input to the next, this is called iteration
(Also see for
loops in Lesson 5).
# Fibonacci sequence
a0 = 1
a1 = 1
a2 = a1+a0
a3 = a2+a1
a4 = a3+a2
a5 = a4+a3
print(a0, a1, a2, a3, a4, a5)
You also saw this after the end of the task in Week 2 when putting the previously calculated value for \(A_g\) back into the next calculation iterated to the correct answer.
Reminder on updating variables:¶
Remember that when we assign values to a variable using
the equals sign we
first take the expression on the
right then assign it to the variable on the left of the
=
.
Therefore we should not interpret a=b
in the mathematical sense
of equality, but assigning the value of b to a.
This can be used to update a variable to a new value that depends on the old one:
a = 1
a = a+1
print(a)
a = a/4.0
print(a)
In this example Python first adds one to the old value of a
then overwrites a with this new value.
Iterating with WHILE Loops¶
A conditional statement such as a>b
can be used to perform some action repeatedly until the condition is no longer true.
This is called a “while
loop”, since it will continue repeating a block of code while the statement remains true.
Once the condition is no longer true the loop will be exited and the last value used.
In the following example we print square numbers as long as the base number is less than 10:
number = 1
while number <= 10: # check the condition to see whether to skip or run the block
square = number**2 # the block is run if the condition is true
print(number, square) # each line is executed in order
number = number + 1 # the values being compared MUST CHANGE or the block will loop forever!
# at the end of the block the condition is checked again and the program moves on if False
print('end of loop')
Exercise: Fibonacci Sequence¶
Follow the instruction in the #
comment to iterate the sequence to iterate until \(a\) reaches \(100\).
Hint: The sequence above can be re-written:
# Fibonacci sequence
a0 = 1
a1 = 1
a2 = a1+a0 #equals 2
a0 = a1 # set a0 to the previous value of a1
a1 = a2 # set a1 to the previous value of a2 = 2
a2 = a1+a0 # re-calculate a2 = 3
a0 = a1 # set a0 to ... a1 = 2
a1 = a2 # set a1 to 3
a2 = a1+a0 # re-calculate a2 = 5
and so on…
# set first value
a0 = 1
print(a0)
# set second value
a1 = 1
print(a1)
# calculate third value
a2 = a1+a0
print(a2)
# put the following block in a while loop to iterate then stop when a goes over 100
# YOUR CODE HERE
Why is the last value greater than 100?
Example: Square Root Iteration¶
Background¶
The value of \(\sqrt{2}\) can be calculated by iteration using: \(x_n = \dfrac{1}{2}\left(x_{n-1} + \dfrac{2}{x_{n-1}}\right)\)
An example iterating this for 10 steps is given below:
x=1 # initial value for x
print(x**2)
i=0 # set a counter
while i<10:
x = 0.5*(x + 2/x)
print(x**2) # show how close x is to sqrt(2)
i=i+1
It only takes a few iterations to get very close to \(\sqrt 2\)
Lets see how the sequence converges by looking at the difference between steps:
x=1 # initial value for x
print(x**2)
i=0 # set a counter
while i<10:
x_old = x
x = 0.5*(x_old + 2/x_old)
difference = x - x_old
print(x**2, difference) # print the "error" from the true value
i=i+1
The difference
term is a measure of the precision (or error) of the current value.
we can define the
while
loop to run while the magnitude of this error is greater than some desired precision (e.g.1e-6
)Note the
abs(VALUE)
has to be used as the difference is negative so always below our precision!
x=1 # initial value for x
print(x**2)
difference = 10 # set this initially above the tolerance
while abs(difference) > 1e-6:
x_old = x
x = 0.5*(x_old + 2/x_old)
difference = x - x_old
print(x**2, difference) # print the "error" from the true value
Note that the last printed value is the first one where the error is below the desired precision.
Exercise: The \(\pi\) sequence¶
The constant \(\pi\) can be obtained using the infinite sequence: \(\pi = 4\left( 1 - \dfrac{1}{3} + \dfrac{1}{5} - \dfrac{1}{7} + \dfrac{1}{9} - \cdots \right)\).
The following two code cells reuse variables to iteratively add to the sequence in the brackets.
run the cell below to assign an initial value to s (the first term in the brackets above)
observe how \(s_2 = s_1 - \dfrac{1}{3}\) (the first two terms in the brackets)
# series pi, using pi/4 = 1 - 1/3 + 1/5 - 1/7 + 1/9 ...
s = 1
print(4*s)
n = -1.0 # set the sign of the next term to be negative
d = 3.0
s = s + n/d # take old value then add next term in sequence (-1/3.0)
print(4*s)
Run the cell below & notice that the sign of
n
changes from-1
to1
andd
changes from3
to5
to add on another term of the series.
n = -1*n # change the sign of the next term by multiplying by -1
d = d + 2 # add 2 to the denominator
s = s + n/d
print(4*s)
Re-run the cell above (use
Ctrl-Enter
) many times over and observe the value of4*s
as it gets closer to \(\pi\)
The above iteration repeats the same steps again and again to accomplish the task.
However it will take many iterations to approximate to the answer well.
A while
loop can now be used to calculate \(\pi\) to a given precision.
Exercise: using the \(\sqrt 2\) example to guide you, write program to calculate \(\pi\) to a given precision¶
keep track of the changes between each iteration of the \(\pi\) sequence
(the so called error term, or correction to each step of the calculation),exit the loop once the absolute error is below (not larger than) some precision.
count the number of steps it takes using a counter
i
which increments on each iteration of the loop.
If your program gets stuck (in an infinite loop) you will see
In [*]
for a long time (more than a few seconds):
if this happens STOP THE KERNEL (square stop button next to>| Run
)
# series pi, using pi/4 = 1 - 1/3 + 1/5 - 1/7 + 1/9 ...
# set initial values
# YOUR CODE HERE
#calculate first two terms
#s = ...
# YOUR CODE HERE
# set any initial value for err that is larger than the condition in the while:
#err = ...
# YOUR CODE HERE
# define a counter to count the steps
i = 0 # set the counter i
# start a while loop with a condition based on the absolute error
#while ???:
# YOUR CODE HERE
# iterate using the pi example above as a model
# iterating the counter and keeping track of the error (it MUST CHANGE each iteration)
# YOUR CODE HERE
print(4*s, err, i) # print pi, error and number of steps
Expected result: 3.1416426510898874 9.999750006262076e-05 19999
The program should take nearly 20000 iterations to reach a precision of \(1\times10^{-4}\)
if it exits too soon check you are calculating the correct error and comparing to the absolute error
Using Conditionals with Functions¶
If statements are often used inside a function. Consider the following function.
def correct_abs(x):
if x > 0:
y = x
elif x < 0:
y = -x
elif x == 0:
y = 0
return y
print(correct_abs(5))
print(correct_abs(-5))
print(correct_abs(0))
We could also use an
else
part instead of the lastelif
.The code could be made shorter by using
>=
instead of>
and==
.
Exercise: Use an if statement to determine whether a quadratic equation has 0, 1 or 2 real roots.¶
Implement a function that solves the quadratic equation \(a x^2 + b x + c = 0\) given the values of the coefficients.
There are two roots \(x_{1,2} = \dfrac{-b\pm \sqrt{b^2 - 4ac}}{2a}\) if the discriminant \(b^2 - 4ac > 0\).
There is only one root \(x = \dfrac{-b}{2a}\) if the discriminant is zero.
There are zero real roots otherwise.
The function should take \(a\), \(b\) and \(c\) as arguments.
It should not return any results, but print the number of solutions followed by the solutions (if any).
#def ???:
# YOUR CODE HERE
#disc = ???
# YOUR CODE HERE
if disc > 0:
#x1 = ???
#x2 = ???
# YOUR CODE HERE
print("2 roots =", x1, x2)
#elif ???:
#???
#print(???)
# YOUR CODE HERE
#???
#???
# YOUR CODE HERE
quads(1, 0, -1)
quads(1, 2, 1)
quads(1, 0, 1)
Expected Result:
2 roots = 1.0 -1.0
1 root = -1.0
0 roots
Summary¶
# conditionals
a = -1
if a > 0 and type(a) == int:
print("positive integer")
elif a < 0 or type(a) != int:
print("negative or not an integer")
else:
print("zero!")
#while loops
def lessthanten(x):
n=0
while x>=10:
n+=1
x=x/10
print(x, end=' ')
print() #blank line
return str(n)+" iterations"
start=1000000
y=lessthanten(start)
print(y)
Pitfalls¶
Watch out for the following sources of errors:
Missing colon before indentation block.
Wrong or inconsistent indentation. Use for 4 spaces (not tabs) per indentation level.
If you use an if statement without an else clause, make sure you know exactly what you are doing.
Make sure all possible cases are covered in an
if
statement.Consider special cases and corner cases, e.g, zero, negative values, first and last possible values, etc.
Task 4 - (2%)¶
Background 1: The \(\operatorname{sinc}\) function¶
The \(\operatorname{sinc}\) function, defined by: \(\operatorname{sinc}(x) = \dfrac{\sin(x)}{x}\)
is an important function in science and engineering.
Background 2: Newton’s method¶
To find the zeros (roots) of the function we use Newton’s method (you will see in Maths 1):
\(x_1 = x_0 - \dfrac{g(x_0)}{g'(x_0)}\).
Task: Write a script using functions and a while loop to find the roots of the sinc function.¶
Define a function to apply the Newton method \(\left( x_1 = x_0 - \dfrac{f(x_0)}{f'(x_0)}\right)\) to any function \(f(x)\),
The function should take a dummy function
f
as one of its arguments, along with an initial pointa
.Inside it should contain a
while
loop to iterate the Newton method to the desired tolerance.you will need to revisit numerical differentiation from the
functions
lessonYour function should have a similar structure to the \(\pi\) sequence example above.
Use both a tolerance
err=1e-6
and differentiation stepdx=1e-6
of \(10^{-6}\)
General Tips¶
Below is the basic template as implied in the question:
#SOME FUNCTION DEFINITION(S)
#A newton function containing a `while` LOOP to watch the absolute error term:
#some maths that works out the derivatives needed for the Newton method given in the question
#the error term is the correction to the previous `x` value
#update `x` using this error term in the Newton formula
#print the values starting from a few initial guess values:
Common Pitfalls¶
Division by zero (use an
if SOMETHING:
statement and setx
to be nearly zero).Not remembering to compare the absolute error in the
while
loop (i.e. it can go negative too).Choosing inappropriate starting values.
Not resetting the error term to be larger than the condition for each while loop (see below).
from math import sin, pi, cos
#define the sinc function with an argument x
def sinc(x):
# condition to stop division by zero for x=0
# YOUR CODE HERE
#return the sinc function
# YOUR CODE HERE
#define a function for newton iteration with a function and a value as arguments
def newton(f, x):
#while loop iteration for newton method down to some precision
# YOUR CODE HERE
return x
#test sinc(0)
s = sinc(0)
print(s)
#test case 1:
r1 = newton(sinc, 1)
print(r1) #sin has a root at zero
#test case 2:
r1 = newton(sin, 1)
print(r1) #sin has a root at zero
#test case 3:
r2 = newton(cos, 1)
print(r2) # sinc does not, but has one at pi
Test your code by running it in the cell above with a fresh kernel and then running the cell below:¶
Only works in ACE Jupyterhub online.
Copy into Spyder to double check and also to save as a plain Python
.py
script file.
#this will only work running on ace.jupyterhub.bath.ac.uk
import sys
sys.path.append('.checks/')
import check04
check04.test(newton, sinc)