# A series that converges to the value of $\pi$
More about loops
We have already encountered one way of repeating calculations - the while
loop. Python also provides a second kind of loop, the for
loop. This allows us to do a calculation for each of the entries in a list, tuple or dictionary (or, more generally, any object that can yield
a well-defined return value each time it is called).
The For loop
Typically, a for
loop takes the form:
for <variable> in <collection>:
<variable>] [calculations using
As with the while
loop, everything within the indented block is executed multiple times, with the <variable>
getting set equal to a different element of <collection>
on each pass. <collection>
may be any ‘iterable’, such as a list. For example, the following code would calculate the sum of all the entries in a
:
= [1, 5, 9]
a = 0
s for x in a:
+= x
s print(x, s)
print("Total is:", s)
It is possible to use continue
[go to the next iteration immediately] and break
[terminate the loop immediately] statements within a for
loop, just as in a while
loop.
Often, we simply want to perform a calculation \(n\) times, counting off as we go. To allow this, Python provides the range
function, which is a special kind of iterable. It can be used as follows:
= 20
n for i in range(n):
print(i)
By default, the counting starts from 0, and continues up to \(n-1\) (so that there are a total of \(n\) passes through the loop). If you want to start from a different number, you can provide this:
= 3
istart = 15
istop for i in range(istart, istop):
print(i)
Notice that the counting starts with istart
, and finishes with istop-1
. We can also count in increments of istep
:
= 3
istart = 15
istop = 4
istep
for i in range(istart, istop, istep):
print(i)
This will print istart
, istart + istep
, istart + 2*istep
etc, but not any value equal to or greater than istep
.
A loop to calculate \(\pi\)
The value of \(\pi\) can be found via an infinite sum \(\pi = 2 \sum_{k=0}^\infty 2^k (k!)^2 / (2k+1)!\), where \(n!\) denotes the factorial of \(n\), i.e., \(n! = n(n-1)(n-2)\ldots 1\). This can be computed by initialising a variable to contain the value 1
, and then looping through the integers up to n
multiplying the variable by each.
enumerations
Often, we may need to iterate through a collection of objects (such as a list), but also keep a count of how many objects we have dealt with.
There are various ways this could be done - one might be:
= [3, 5, 7]
a for i in range(len(a)):
print("Object number", i, " is ", a[i])
However, Python provides the enumerate
function for precisely this purpose:
= [3, 5, 7]
a for i, ai in enumerate(a):
print("Object number", i, " is ", ai)
The iterable created by enumerate
returns a tuple of (index, object)
pairs, which can be assigned to a pair of variables (here, i
and ai
).
zip
Another common circumstance is that we have two (or more) collections, and we want to access the \(i\)-th element of each simultaneously. Again, this could be achieved using something like:
= [3, 5, 7]
a = ['a', 'b', 'c']
b for i in range(len(a)):
print("The letter associated with ", a[i], " is ", b[i])
but Python also provides the zip
function for this purpose:
= [3, 5, 7]
a = ['a', 'b', 'c']
b for ai, bi in zip(a, b):
print("The letter associated with ", ai, " is ", bi)
This creates an iterator which returns a tuple on each iteration, containing the \(i\)-th element of each of the collections passed to zip
. The elements of this tuple can be assigned to variables (here, ai
and bi
).
Now, you start crossing out numbers. First, we consider the first entry in the list, 2. We keep this, but cross out every second number thereafter:
2 3 X 5 X 7 X 9 X 11 X 13 X 15 X 17 X 19 X 21 X 23 X 25
^Start here
We move our pointer to the next not-crossed-out number, 3. We then cross out every 3rd entry (counting ones that are already crossed out):
2 3 X 5 X 7 X X X 11 X 13 X X X 17 X 19 X X X 23 X 25
^Start here
The next not-crossed out number is 5, so we remove every 5th entry:
2 3 X 5 X 7 X X X 11 X 13 X X X 17 X 19 X X X 23 X X
^Start here
If we continue this procedure, we will find that we do not cross out any more numbers. The remaining numbers - 2, 3, 5, 7, 11, 13, 17, 19 and 23 - are all the primes less than (or equal to) 25.