References
WC3 Python While Loops
WC3 Schools: Tutorial: Python For Loops
In the next example we use a while loop to compute the factorial of a number. Note the condition n>1. The last time the loop is entered n is 2 and fa=fa*(2-1).
Updated 8/26/23
Donald Falkenburg
The first example is to calculate the factorial of a number n. Here n is assigned a value of 5. Computing the factorial repeatedly multiplying the number by (n-1). This continues while n>1. Each pass thru the loop, n is decremented by one.
# Ex1.5.1
n=5
f=n
while n > 1:
f=f*(n-1)
n+=-1 #this is the same as n=n-1
print("5!=",f)
5!= 120
Actually, there is not reason to write a script to compute the factorial. The math package math contains a function to do this. In the following example, we employ this function. In addition, we have added an ability for the user to input the number n to compute n! The function input( ) contains an argument which will be printed on the console to prompt the user. After entering the number the user must use return. IMPORTANT NOTE: The input( ) function always reads a string. Thus, if you enter 5, for example, it the representation in the program will be '5' a string. Thus, it is essential to convert this to an integer in order to use the factorial function. this is why the argument of mth.factorial(int(n)) contains the casting function int().
# Ex1.5.2
import math as mth
n=input("enter an integer\n")
print(n,"!=",mth.factorial(int(n)))
enter an integer 5 5 != 120
Euler's number e is an irrational number approximated by 2.71828. It can be computed using the infinite series $1.0+\sum_{n=1}^\infty \frac{1}{n!}$ We will write a program to compute the sum of this series until until the nth term is less than $10^{-6}$. Like Ex 1.5.1a, we use the math package to compute the n! The while loop computes terms in the series and truncates after a term is less than $10^{-6}$. The first print statement (line 10) prints out the number of terms in the series at truncation, while the next statement prints the estimated value of e computed. The final print is again something new. The f"{...}" indicates that we are printing an f-string. The variable is sum, and the :.6f indicates the precision of the output. Notice comparing the two outputs, it is clear that this does not just truncate, but it rounds to achieve the 6 significant figures in the result. We will spend more time on this in a later module. Reference: https://blog.teclado.com/python-formatting-numbers-for-printing/
# Ex1.5.3
import math as mth
sum=1.0
ds=1.0
n=1
while ds > .000001 :
ds=1.0/mth.factorial(n)
sum=sum+ds
n+=1
print("summing",n, "terms in the series\n")
print("e=",sum)
print("\nthe value of e to six signifigant figures\n")
print("e=",f"{sum:.6f}")
summing 11 terms in the series e= 2.7182818011463845 the value of e to six signifigant figures e= 2.718282
The while loop is executed as long as the condition is True. In the for loop, iteration continues a countable number of times. Here is an example of a countable number of iterations. In Ex1.5.2 we want to find the frequency of random draws from a probability distribution, in which the values between 0 and 1 are uniformly distributed.
# Ex1.5.4
import random as rnd
b0=[] #list of values of random draw .0<x<=.2
b1=[] #list of values of random draw .2<x<=.4
b2=[] #list of values of random draw .4<x<=.6
b3=[] #list of values of random draw .6<x<=.8
b4=[] #list of values of random draw .8<x<=1.0
for n in range(1000):
x=rnd.uniform(0,1)
if(x>=0 and x<=.2): b0.append(x)
if(x>.2 and x<=.4): b1.append(x)
if(x>.4 and x<=.6): b2.append(x)
if(x>.6 and x<=.8): b3.append(x)
if(x>.8 and x<=1.0): b4.append(x)
print("frequency in [0,.2) ", len(b0)/1000)
print("frequency in (.2,.4] ", len(b1)/1000)
print("frequency in (4,.6] ", len(b2)/1000)
print("frequency in (.6,.8] ", len(b3)/1000)
print("frequency in (.8,1.0]", len(b4)/1000)
frequency in [0,.2) 0.179 frequency in (.2,.4] 0.218 frequency in (4,.6] 0.189 frequency in (.6,.8] 0.203 frequency in (.8,1.0] 0.211
In the next example, we will look at how the random draws more closely approximate a uniform distribution as the number of trials increases. In order to do this we will nest the for loop (lines 10 to 23). This for loop is nested inside an outer loop (lines 4-23). In each pass through the outer loop we will increase the number of trials by a factor of 10.
# Ex1.5.5
import random as rnd
m=10
for i in range(4):
b0=[] #list of values of random draw .0<x<=.2
b1=[] #list of values of random draw .2<x<=.4
b2=[] #list of values of random draw .4<x<=.6
b3=[] #list of values of random draw .6<x<=.8
b4=[] #list of values of random draw .8<x<=1.0
for n in range(m):
x=rnd.uniform(0,1)
if(x>=0 and x<=.2): b0.append(x)
if(x>.2 and x<=.4): b1.append(x)
if(x>.4 and x<=.6): b2.append(x)
if(x>.6 and x<=.8): b3.append(x)
if(x>.8 and x<=1.0): b4.append(x)
print("\n The number of random draws=",m)
print("frequency in [0,.2] ", len(b0)/m)
print("frequency in (.2,.4] ", len(b1)/m)
print("frequency in (4,.6] ", len(b2)/m)
print("frequency in (.6,.8] ", len(b3)/m)
print("frequency in (.8,1.0]", len(b4)/m)
m=m*10
The number of random draws= 10 frequency in [0,.2] 0.2 frequency in (.2,.4] 0.1 frequency in (4,.6] 0.3 frequency in (.6,.8] 0.4 frequency in (.8,1.0] 0.0 The number of random draws= 100 frequency in [0,.2] 0.25 frequency in (.2,.4] 0.19 frequency in (4,.6] 0.21 frequency in (.6,.8] 0.14 frequency in (.8,1.0] 0.21 The number of random draws= 1000 frequency in [0,.2] 0.186 frequency in (.2,.4] 0.179 frequency in (4,.6] 0.219 frequency in (.6,.8] 0.199 frequency in (.8,1.0] 0.217 The number of random draws= 10000 frequency in [0,.2] 0.2021 frequency in (.2,.4] 0.2028 frequency in (4,.6] 0.2004 frequency in (.6,.8] 0.2028 frequency in (.8,1.0] 0.1919
The range() function used in the for loop takes on up to three parameters: range(start_value,stop_value,step_value). You can use one, two, or all three parameters. Using one paramter establishes the stop value Up until now we used for n in range(5): . Using two parameters establishes both the start and stop values. Adding a third parameter specifies the step size. NOTE: THE CODE BLOCK EMBEDDED IN THE FOR LOOP IS NOT EXECUTED IF n is greater or equal to* the Stop_value. IN THE CASE IN WHICH WE USE ONLY ONE PARAMETER, AND THE ITERATION BEGINS AT 0, THE STOP_VALUE EQUALS THE NUMBER OF ITERATIONS.
Notice that in the following program we have three different for loops. Each loop has a SINGLE statement. In that case, there is no need to use indentation to denote a block of code. Simply place the single statement in line following the :
# Ex1.5.6
print("Using range(5)")
for i in range(5): print(i)
print("Using range(1,5)")
for i in range(1,5): print(i)
print("Using range(0,5,2)")
for i in range(0,5,2):print(i)
Using range(5) 0 1 2 3 4 Using range(1,5) 1 2 3 4 Using range(0,5,2) 0 2 4
Look at the results again. The start_value does print, but the stop_value does not print! Remember The loop does not execute if i is greater than or equal to the stop_value.
An alternate construction for the for loop is given by for x in [list of objects] In the following example we mix both floating point numbers and an integer in the list of objects.
# Ex1.5.6
for x in [2.0,4.7,16]:
print(x)
2.0 4.7 16
In Ex1.5.6 our outer for loop changed the number of random draws by a computed number m=m*10. Suppose we wanted to look at random draws over a list of values [1,10,50,100] This requires us to change the outer for loop to use for i in [1,10,50,100]: We need to get rid of the variable m (which we used in 1.5.6 to establish the step size. The variable i (drawn from the list) is the number of samples to draw from uniform. The frequency is found by taking the number of elements in the several bins and dividing by i. Note we now see more clearly how sample size affects the frequency of of the draw.
# Ex1.5.7
import random as rnd
for i in [1,10,50,100]:
b0=[] #list of values of random draw .0<x<=.2
b1=[] #list of values of random draw .2<x<=.4
b2=[] #list of values of random draw .4<x<=.6
b3=[] #list of values of random draw .6<x<=.8
b4=[] #list of values of random draw .8<x<=1.0
for n in range(i):
x=rnd.uniform(0,1)
if(x>=0 and x<=.2): b0.append(x)
if(x>.2 and x<=.4): b1.append(x)
if(x>.4 and x<=.6): b2.append(x)
if(x>.6 and x<=.8): b3.append(x)
if(x>.8 and x<=1.0): b4.append(x)
print("\n The number of random draws=",i)
print("frequency in [0,.2] ", len(b0)/i)
print("frequency in (.2,.4] ", len(b1)/i)
print("frequency in (4,.6] ", len(b2)/i)
print("frequency in (.6,.8] ", len(b3)/i)
print("frequency in (.8,1.0]", len(b4)/i)
The number of random draws= 1 frequency in [0,.2] 0.0 frequency in (.2,.4] 0.0 frequency in (4,.6] 1.0 frequency in (.6,.8] 0.0 frequency in (.8,1.0] 0.0 The number of random draws= 10 frequency in [0,.2] 0.4 frequency in (.2,.4] 0.2 frequency in (4,.6] 0.1 frequency in (.6,.8] 0.0 frequency in (.8,1.0] 0.3 The number of random draws= 50 frequency in [0,.2] 0.28 frequency in (.2,.4] 0.24 frequency in (4,.6] 0.12 frequency in (.6,.8] 0.2 frequency in (.8,1.0] 0.16 The number of random draws= 100 frequency in [0,.2] 0.2 frequency in (.2,.4] 0.17 frequency in (4,.6] 0.21 frequency in (.6,.8] 0.27 frequency in (.8,1.0] 0.15
Note: we again take advantage of using a single in-line statement for the if, and we again use the incrementation operator +=
# Ex1.5.8
animals=["dog", "cat","mouse","dog","elephant","bear","dog"]
x="dog"
count=0
for animal in animals:
if animal==x: count+=1
print(animal,"occurs",count,"times in the list of animals")
dog occurs 3 times in the list of animals
Ex 1.5.8 contains the application of several concepts previously introduced. In this example we are given some text which is assigned to the variable sentence. We want to iterate through the characters in this string and count the number of vowels, consonants, spaces, and other non-letter characters. In order to do this we define two tuples--one containing the vowels and one containing consonants (lines 9 & 10). We realize that the characters "a" and "A" are different characters. We have two choice. We could extend the two tuples we defined to also hold upper case characters, or we can use a method which is defined for strings that will change all upper case characters to lower case. We do this by defining a new string variable lstring=sentence.lower() line 11. The iteration loop is in lines 12 to 16. Here we see a new concept of iteration through the elements (x) of a string (line 12). We then use an if statement to determine if x is in the tuple containg vowels, or consonants, or if x is a space. In each of these cases we increment a counting variable. If none of these are true, then the character must be a punctuation mark or other non-letter character. Instead of a series of if/else statements, we use if/elif/elif/else. We can actually have as many elif's as needed to accomplish the task set before us.
# Ex1.5.9
sentence="Python has been an object-oriented language since it existed. Because of this, creating and using classes and objects are downright easy."
print(sentence)
N1=0 #number of vowels
N2=0 #number of consonants
N3=0 #number of spaces
N4=0 #number of other characters (includes punctuation marks, special characters)
N=len(sentence) #total number of characters in string
vowel=("a","e","i","o","u")
consonant=("b","c","d","f","g","h","j","k","l","m","n","p","q","r","s","t","v","w","x","y","z")
lstring=sentence.lower()
for x in lstring:
if x in vowel: N1+=1 #increment vowel count
elif x in consonant: N2+=1
elif x==" ": N3+=1 #increment spaces count
else: N4+=1 #increment non-space and non-vowel
print("number of characters in sentence=",N)
print("number of vowels=",N1)
print("number of consonants=",N2)
print("number of spaces=",N3)
print("number of other characters=",N4)
Python has been an object-oriented language since it existed. Because of this, creating and using classes and objects are downright easy. number of characters in sentence= 137 number of vowels= 44 number of consonants= 69 number of spaces= 20 number of other characters= 4