Lesson 09 - While Loops

The following topics are discussed in this notebook:

  • while loops
  • Reading user input

Additional Resources

While Loops

A while loop is similar to a for loop in that it is a tool used to automate a repetive task. The core difference between while and for loops is as follows:

  • A for loop executes a predetermined number of times. A for loop that begins with "for i in range(a,b)" will execute exactly once for each value of the counter i that falls within the given range.
  • A while loop executes as long as some supplied condition is true. Depending on the nature of this condition, we do not necessarily know ahead of time how many times the loop will execute.

At a basic level, for loops and while loops behave similarly, as shown by the following examples.

In [1]:
n = 0
while n < 10:
    print(n**2)
    n += 1

The task above could have been accomplished more succintly using a for loop:

In [2]:
for n in range(0,10):
    print(n**2)
0
1
4
9
16
25
36
49
64
81

The usefulnes of while loops arises from sitautions in which we aren't sure how many times the loop should execute.

As a simple example, lets say that we want to print out all perfect squares less than 1000.

In [3]:
x = 0
while x**2 < 1000:
    print(x**2)
    x += 1
0
1
4
9
16
25
36
49
64
81
100
121
144
169
196
225
256
289
324
361
400
441
484
529
576
625
676
729
784
841
900
961

� Exercise

Find the largest power of 2 less than 10,000. Print this number.

In [4]:
n = 0
while 2**n < 10000:
    n +=1 

print(2**(n-1))
8192

� Exercise

Find the smallest integer n whose factorial is greater than 1,000,000. Once you have found n, print the following two messages:

The smallest integer whose factorial is less than 1,000,000 is [n].
[n] factorial is equal to [n!]. 
In [5]:
n = 1
nFact = 1

while nFact < 1000000:
    n +=1 
    nFact = nFact * n

print("The smallest integer whose factorial is less than 1,000,000 is " + str(n) + ".")
print(str(n) + " factorial is equal to " + str(nFact) + ".")
The smallest integer whose factorial is less than 1,000,000 is 10.
10 factorial is equal to 3628800.

� Exercise

Determine the number of times that 2 evenly divides 3,620,864. In other words, determine how many factors of 2 are in 3,620,864. Print the message:

3,620,864 can be divided by 2 a total of [count] times. 
In [6]:
x = 3620864
count = 0

while(x % 2 == 0):
    
    x = x/2
    count += 1
    
print("3,620,854 can be divided by 2 a total of " + str(count) + " times.")
3,620,854 can be divided by 2 a total of 14 times.

� Exercise

Find all of the factors of the number 14,267,352. Store the factors in a list called factors. Print this list.

In [7]:
x = 14267352
fctr = 2
factors = []

while(x > 1):
    while(x % fctr == 0):
        x = x / fctr
        factors.append(fctr)    
    fctr += 1
    
print(factors)
[2, 2, 2, 3, 11, 11, 17, 17, 17]

User Input

Programs often require input from the user. Python's input() function provides a method of prompting the user for input. For example, consider the following code:

name = input("What is your name? ")

This code will print the string, "What is your name? " and will then wait for user input. The value entered by the user will then be stored in the variable myVar.

In [8]:
name = input("What is your name? ")
print("Hello, " + name + "!")
What is your name? Robbie
Hello, Robbie!

User input can be combined with while loops to create interactive programs.

In [9]:
import random
n = random.choice(range(0, 1000))


print("I have selected a random number between 0 and 999, inclusive. Can you guess it?")

done = False
count = 1
while done == False:
    
    guess = int(input("Please enter guess number " + str(count) + ": "))
    
    if(guess < n):
        print("Your guess was too small.")
    elif(guess > n):
        print("Your guess was too large.")
    else:
        print("That's it! It took you " + str(count) + " guesses to find the right answer.")
        done = True
        
    count += 1
    
I have selected a random number between 0 and 999, inclusive. Can you guess it?
Please enter guess number 1: 500
Your guess was too large.
Please enter guess number 2: 250
Your guess was too large.
Please enter guess number 3: 125
Your guess was too large.
Please enter guess number 4: 62
Your guess was too small.
Please enter guess number 5: 90
Your guess was too small.
Please enter guess number 6: 105
Your guess was too small.
Please enter guess number 7: 115
Your guess was too small.
Please enter guess number 8: 120
Your guess was too small.
Please enter guess number 9: 123
Your guess was too large.
Please enter guess number 10: 122
That's it! It took you 10 guesses to find the right answer.

� Exercise

Newton's Method is a calculus-based technique for finding approximate solutions to mathematical equations. We will not discuss the details of Netwon's Method here, but one application of this technique is finding square roots of numbers. The process works as follows:

  • Assume that we want to calculuate $\sqrt K$.
  • We start by making an initial guess, that we will denote by $x_1$.
  • We can improve our estimate by calculating $x_2 = x_1 - \frac{x_1^2 - K}{2 \cdot x_1}$
  • We can continue to make impovements by continuing this process.
  • In general, our nth guess is given by: $x_n = x_{n-1} - \frac{x_{n-1}^2 - K}{2 \cdot x_{n-1}}$

Apply this technique 10 times to approximate the square root of 734,123,454,324.

In [10]:
# K is the number whe want to take the square root of.
K = 734123454324

# x will be equal to our first guess
x = 5

# We will create a loop that runs 10 times, improving our guess each time.
for i in range(0,10):
    x = x - (x**2 - K) / (2*x)
    
print(x)
143385193.8336325

It tuns out that the true square root of 734,123,454,324 is approximately 856,810.0457. Our approximation is way off. We didn't let the algorithm run enough times.

Let's try again with a while loop. We will continue to make improvements on our estimate until two consecutive estimates are within 1/1000 of each other.

In [11]:
# K is the number whe want to take the square root of.
K = 734123454324

# x will be equal to our first guess
x = 5

# We create a flag that tells us when to stop
keep_going = True


# We will create a loop that runs 10 times, improving our guess each time.
while (keep_going):

    for i in range(0,10):
        x_old = x
        x = x - (x**2 - K) / (2*x)
        
        diff = x_old - x
        
        # We need to take the absolute value of diff
        if diff < 0:
            diff = -diff
        
        if(diff < 0.001):
            keep_going = False
            
print(x)
856810.0456483923