This chapter is taken from the book A Primer on Scientific Programming with Python by H. P. Langtangen, 5th edition, Springer, 2016.
Write a Python program that prints out a table with Fahrenheit degrees \( 0, 10, 20, \ldots, 100 \) in the first column and the corresponding Celsius degrees in the second column.
Hint.
Modify the c2f_table_while.py
program from the section While loops.
Filename: f2c_table_while
.
Many people use an approximate formula for quickly converting Fahrenheit
(\( F \)) to
Celsius (\( C \)) degrees:
$$
\begin{equation}
C \approx \hat C = (F-30)/2
\tag{2}
\end{equation}
$$
Modify the program from Exercise 1: Make a Fahrenheit-Celsius conversion table so that
it prints three columns: \( F \), \( C \), and the approximate value \( \hat C \).
Filename: f2c_approx_table
.
Set a variable primes
to a list containing the numbers
2, 3, 5, 7, 11, and 13.
Write out each list element in a for
loop.
Assign 17 to a variable p
and add p
to the end of the list.
Print out the entire new list.
Filename: primes
.
Write a program that generates all odd numbers from 1 to n
.
Set n
in the beginning of the program and use a while
loop
to compute the numbers. (Make sure that if n
is an even number,
the largest generated odd number is n-1
.)
Filename: odd
.
Write a program that computes the sum of the integers from 1 up to
and including \( n \). Compare the result with the famous formula
\( n(n+1)/2 \).
Filename: sum_int
.
The \( n \)-th energy level for an electron in a Hydrogen atom is given by $$ E_n = -\frac{m_e e^4}{8\epsilon_0^2h^2}\cdot\frac{1}{n^2} , $$ where \( m_e = 9.1094\cdot 10^{-31} \) kg is the electron mass, \( e = 1.6022\cdot 10^{-19} \) C is the elementary charge, \( \epsilon_0 = 8.8542\cdot 10^{-12} \) C$^2$s$^2$ kg$^{-1}$ m$^-3$ is the electrical permittivity of vacuum, and \( h = 6.6261\cdot 10^{-34} \) Js.
a) Write a Python program that calculates and prints the energy level \( E_n \) for \( n=1,\ldots , 20 \).
b) The released energy when an electron moves from level \( n_i \) to level \( n_f \) is given by $$ \Delta E = -\frac{m_e e^4}{8\epsilon_0^2h^2}\cdot\left( \frac{1}{n_i^2}-\frac{1}{n_f^2}\right) \tp $$ Add statements to the program from a) so that it prints a second, nicely formatted table where the cell in column \( i \) and row \( f \) contains the energy released when an electron moves from energy level \( i \) to level \( f \), for \( i,f = 1,\ldots , 5 \).
Filename: energy_levels
.
We want to generate \( n+1 \) equally spaced \( x \) coordinates in \( [a,b] \). Store the coordinates in a list.
a)
Start with an empty list, use a for
loop and append each
coordinate to the list.
Hint. With \( n \) intervals, corresponding to \( n+1 \) points, in \( [a,b] \), each interval has length \( h=(b-a)/n \). The coordinates can then be generated by the formula \( x_i=a+ih \), \( i=0,\ldots,n+1 \).
b) Use a list comprehension as an alternative implementation.
Filename: coor
.
The purpose of this exercise is to write code that prints a nicely formatted table of \( t \) and \( y(t) \) values, where $$ \begin{equation*} y(t) = v_0t - \frac{1}{2}gt^2\tp\end{equation*} $$ Use \( n+1 \) uniformly spaced \( t \) values throughout the interval \( [0, 2v_0/g] \).
a)
Use a for
loop to produce the table.
b)
Add code with a while
loop to produce the table.
Hint.
Because of potential round-off errors,
you may need to adjust the upper limit of the while
loop to
ensure that the last point (\( t=2v_0/g \), \( y=0 \)) is included.
Filename: ball_table1
.
This exercise aims to produce the same table of numbers as in Exercise 8: Make a table of values from a formula, but with different code. First, store the \( t \) and
\( y \) values in two lists t
and y
. Thereafter, write out a nicely
formatted table by traversing the two lists with a for
loop.
Hint.
In the for
loop,
use either zip
to traverse the two lists in parallel, or use
an index and the range
construction.
Filename: ball_table2
.
You are given the following program:
a = [1, 3, 5, 7, 11]
b = [13, 17]
c = a + b
print c
b[0] = -1
d = [e+1 for e in a]
print d
d.append(b[0] + 1)
d.append(b[-1] + 1)
print d[-2:]
for e1 in a:
for e2 in b:
print e1 + e2
Go through each statement and explain what is printed by the program.
Filename: simulate_lists
.
The following code is supposed to compute the sum \( s = \sum_{k=1}^M {1\over k} \):
s = 0; k = 1; M = 100
while k < M:
s += 1/k
print s
This program does not work correctly. What are the three errors?
(If you try to run the program, nothing will happen on the screen.
Type Ctrl+c
, i.e., hold down the Control (Ctrl
)
key and then type the c
key, to stop the program.)
Write a correct program.
Hint. There are two basic ways to find errors in a program:
s
with your own
hand calculations.
Filename: sum_while
.
Rewrite the corrected version of the
program in Exercise 11: Compute a mathematical sum using a
for
loop over k
values
instead of a while
loop.
Filename: sum_for
.
Consider the following program for computing with interest rates:
initial_amount = 100
p = 5.5 # interest rate
amount = initial_amount
years = 0
while amount <= 1.5*initial_amount:
amount = amount + p/100*amount
years = years + 1
print years
a)
Use a pocket calculator or an interactive Python shell
and work through the program calculations by hand. Write down
the value of amount
and years
in each pass of the loop.
b)
Set p = 5
instead. Why will the loop
now run forever? (Apply Ctrl+c, see Exercise 11: Compute a mathematical sum, to
stop a program with a loop that runs forever.)
Make the program robust against such errors.
c)
Make use of the operator +=
wherever possible in the program.
d) Explain with words what type of mathematical problem that is solved by this program.
Filename: interest_rate_loop
.
Suppose you want to compute with the inverse sine function: \( \sin^{-1}x \). How do you do that in a Python program?
Hint.
The math
module has an inverse sine function.
Find the correct name of the function by looking up
the module content in the online Python Standard Library document
or use pydoc
, see the section How to find more Python information.
Filename: inverse_sine
.
We define the following nested list:
q = [['a', 'b', 'c'], ['d', 'e', 'f'], ['g', 'h']]
a)
Index this list to extract 1) the letter a
;
2) the list ['d', 'e', 'f']
; 3) the last element h
;
4) the d
element.
Explain why q[-1][-2]
has the value g
.
b)
We can visit all elements of q
using this nested for
loop:
for i in q:
for j in range(len(i)):
print i[j]
What type of objects are i
and j
?
Filename: index_nested_list
.
Modify the program from Exercise 2: Generate an approximate Fahrenheit-Celsius conversion table so that
all the \( F \), \( C \), and \( \hat C \) values are stored in separate lists
F
, C
, and C_approx
, respectively.
Then make a nested list conversion
so that
conversion[i]
holds a row in the table: [F[i], C[i], C_approx[i]]
.
Finally, let the program traverse the conversion
list and write
out the same table as in Exercise 2: Generate an approximate Fahrenheit-Celsius conversion table.
Filename: f2c_approx_lists
.
The purpose of this exercise is to store tabular data in two alternative ways, either as a list of columns or as a list of rows. In order to write out a nicely formatted table, one has to traverse the data, and the technique for traversal depends on how the tabular data is stored.
a)
Compute two lists of \( t \) and \( y \) values as explained
in Exercise 9: Store values from a formula in lists. Store the two
lists in a new nested list ty1
such that ty1[0]
and ty1[1]
correspond to the two lists.
Write out a table with \( t \) and \( y \)
values in two columns by looping over the data in the ty1
list.
Each number should be written with two decimals.
b)
Make a list ty2
which holds each row in the table
of \( t \) and \( y \) values (ty1
is a list of table columns while
ty2
is a list of table rows, as explained in the section Nested lists). Loop over the ty2
list and write out the \( t \) and \( y \)
values with two decimals each.
Filename: ball_table3
.
Explain the outcome of each of the following boolean expressions:
C = 41
C == 40
C != 40 and C < 41
C != 40 or C < 41
not C == 40
not C > 40
C <= 41
not False
True and False
False or True
False or False or False
True and True and False
False == 0
True == 0
True == 1
It makes sense to compare
True
and False
to the integers 0 and 1,
but not other integers (e.g., True == 12
is False
although
the integer 12 evaluates to True
in a boolean context, as
in bool(12)
or if 12
).
eval_bool
.
Maybe you have tried to hit the square root key on a calculator multiple times and then squared the number again an equal number of times. These set of inverse mathematical operations should of course bring you back to the starting value for the computations, but this does not always happen. To avoid tedious pressing of calculator keys, we can let a computer automate the process. Here is an appropriate program:
from math import sqrt
for n in range(1, 60):
r = 2.0
for i in range(n):
r = sqrt(r)
for i in range(n):
r = r**2
print '%d times sqrt and **2: %.16f' % (n, r)
Explain with words what the program does. Then run the program.
Round-off errors are here completely destroying the calculations when
n
is large enough! Investigate the case when we come back to
1 instead of 2 by fixing an n
value where this happens and printing
out r
in both for
loops over i
.
Can you now explain why we come back to 1 and not 2?
Filename: repeated_sqrt
.
Type in the following code and run it:
eps = 1.0
while 1.0 != 1.0 + eps:
print '...............', eps
eps = eps/2.0
print 'final eps:', eps
Explain with words what the code is doing, line by line.
Then examine the output. How can it be that the
"equation" \( 1\neq 1+ \hbox{eps} \) is not true?
Or in other words, that a number of approximately size \( 10^{-16} \)
(the final eps
value when the loop terminates) gives
the same result as if eps
were zero?
Filename: machine_zero
.
The nonzero eps
value computed above is called machine epsilon or
machine zero and is an important parameter to know, especially when
certain mathematical techniques are applied to control round-off
errors.
Run the following program:
a = 1/947.0*947
b = 1
if a != b:
print 'Wrong result!'
The lesson learned from this program is that one should never compare
two floating-point objects directly using a == b
or a != b
,
because round-off errors quickly make two identical mathematical
values different on a computer. A better result is to test if
abs(a - b) < tol
, where tol
is a very small number. Modify the test
according to this idea.
Filename: compare_floats
.
The function time
in the module time
returns the number
of seconds since a particular date (called the Epoch, which is
January 1, 1970, on many types of computers). Python programs can therefore
use time.time()
to mimic a stop watch. Another function,
time.sleep(n)
causes the program to pause for n
seconds
and is handy for inserting a pause.
Use this information to
explain what the following code does:
import time
t0 = time.time()
while time.time() - t0 < 10:
print '....I like while loops!'
time.sleep(2)
print 'Oh, no - the loop is over.'
How many times is the print
statement inside the loop executed?
Now, copy the code segment and change the <
sign in the loop
condition to a >
sign. Explain what happens now.
Filename: time_while
.
Type in the following program in a file and check carefully that you have exactly the same spaces:
C = -60; dC = 2
while C <= 60:
F = (9.0/5)*C + 32
print C, F
C = C + dC
Run the program. What is the first problem? Correct that error.
What is the next problem? What is the cause of that problem?
(See Exercise 11: Compute a mathematical sum for how to stop a hanging program.)
Filename: indentation
.
The lesson learned from this exercise is that one has to be very careful with indentation in Python programs! Other computer languages usually enclose blocks belonging to loops in curly braces, parentheses, or begin-end marks. Python's convention with using solely indentation contributes to visually attractive, easy-to-read code, at the cost of requiring a pedantic attitude to blanks from the programmer.
Some of the following assignments work and some do not.
Explain in each case why the assignment works/fails and, if it
works, what kind of object x
refers to and what the value is
if we do a print x
.
x = 1
x = 1.
x = 1;
x = 1!
x = 1?
x = 1:
x = 1,
Hint. Explore the statements in an interactive Python shell.
Filename: punctuation
.
Study the following interactive session and explain in detail what happens in each pass of the loop, and use this explanation to understand the output.
>>> numbers = range(10)
>>> print numbers
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> for n in numbers:
... i = len(numbers)/2
... del numbers[i]
... print 'n=%d, del %d' % (n,i), numbers
...
n=0, del 5 [0, 1, 2, 3, 4, 6, 7, 8, 9]
n=1, del 4 [0, 1, 2, 3, 6, 7, 8, 9]
n=2, del 4 [0, 1, 2, 3, 7, 8, 9]
n=3, del 3 [0, 1, 2, 7, 8, 9]
n=8, del 3 [0, 1, 2, 8, 9]
The message in this exercise is to never modify a list that we are looping over. Modification is indeed technically possible, as shown above, but you really need to know what you are doing. Otherwise you will experience very strange program behavior.
for_changing_list
.