$$ \newcommand{\tp}{\thinspace .} $$

 

 

 

This chapter is taken from the book A Primer on Scientific Programming with Python by H. P. Langtangen, 5th edition, Springer, 2016.

The first programming encounter: a formula

The first formula we shall consider concerns the vertical motion of a ball thrown up in the air. From Newton's second law of motion one can set up a mathematical model for the motion of the ball and find that the vertical position of the ball, called \( y \), varies with time \( t \) according to the following formula: $$ \begin{equation} y(t) = v_0t - \frac{1}{2}gt^2\tp \tag{1} \end{equation} $$ Here, \( v_0 \) is the initial velocity of the ball, \( g \) is the acceleration of gravity, and \( t \) is time. Observe that the \( y \) axis is chosen such that the ball starts at \( y=0 \) when \( t=0 \). The above formula neglects air resistance, which is usually small unless \( v_0 \) is large, see Exercise 11: Compute the air resistance on a football.

To get an overview of the time it takes for the ball to move upwards and return to \( y=0 \) again, we can look for solutions to the equation \( y=0 \): $$ \begin{equation*} v_0t - \frac{1}{2}gt^2 = t(v_0 - \frac{1}{2}gt) =0 \quad\Rightarrow\quad t=0\hbox{ or }t=2v_0/g\tp\end{equation*} $$ That is, the ball returns after \( 2v_0/g \) seconds, and it is therefore reasonable to restrict the interest of (1) to \( t\in [0, 2v_0/g] \).

Using a program as a calculator

Our first program will evaluate (1) for a specific choice of \( v_0 \), \( g \), and \( t \). Choosing \( v_0=5 \hbox{ m/s} \) and \( g=9.81 \hbox{ m/}\hbox{s}^2 \) makes the ball come back after \( t=2v_0/g\approx 1\hbox{ s} \). This means that we are basically interested in the time interval \( [0,1] \). Say we want to compute the height of the ball at time \( t=0.6 \hbox{ s} \). From (1) we have $$ \begin{equation} y = 5\cdot 0.6 - \frac{1}{2}\cdot 9.81 \cdot 0.6^2 \tag{2} \end{equation} $$ This arithmetic expression can be evaluated and its value can be printed by a very simple one-line Python program:

print 5*0.6 - 0.5*9.81*0.6**2

The four standard arithmetic operators are written as +, -, *, and / in Python and most other computer languages. The exponentiation employs a double asterisk notation in Python, e.g., \( 0.6^2 \) is written as 0.6**2.

Our task now is to create the program and run it, and this will be described next.

About programs and programming

A computer program is just a sequence of instructions to the computer, written in a computer language. Most computer languages look somewhat similar to English, but they are very much simpler. The number of words and associated instructions is very limited, so to perform a complicated operation we must combine a large number of different types of instructions. The program text, containing the sequence of instructions, is stored in one or more files. The computer can only do exactly what the program tells the computer to do.

Another perception of the word program is a file that can be run ("double-clicked") to perform a task. Sometimes this is a file with textual instructions (which is the case with Python), and sometimes this file is a translation of all the program text to a more efficient and computer-friendly language that is quite difficult to read for a human. All the programs in this document consist of short text stored in a single file. Other programs that you have used frequently, for instance Firefox or Internet Explorer for reading web pages, consist of program text distributed over a large number of files, written by a large number of people over many years. One single file contains the machine-efficient translation of the whole program, and this is normally the file that you double-click on when starting the program. In general, the word program means either this single file or the collection of files with textual instructions.

Programming is obviously about writing programs, but this process is more than writing the correct instructions in a file. First, we must understand how a problem can be solved by giving a sequence of instructions to the computer. This is one of the most difficult things with programming. Second, we must express this sequence of instructions correctly in a computer language and store the corresponding text in a file (the program). This is normally the easiest part. Third, we must find out how to check the validity of the results. Usually, the results are not as expected, and we need to a fourth phase where we systematically track down the errors and correct them. Mastering these four steps requires a lot of training, which means making a large number of programs and getting the programs to work.

Tools for writing programs

There are three alternative types of tools for writing Python programs:

What you choose depends on how you access Python. the document How to access Python for doing scientific computing [1] contains information on the various possibilities to install Python on your own computer, access a pre-installed Python environment on a computer system at an institution, or access Python in cloud services through your web browser.

Based on teaching this and previous books to more than 3000 students, my recommendations go as follows.

Writing and running your first Python program

I assume that you have made a decision on how to access Python, which dictates whether you will be writing programs in a text editor or in an IPython notebook. What you write will be the same - the difference lies in how you run the program. the document How to access Python for doing scientific computing [1] briefly describe how to write programs in a text editor, run them in a terminal window or in Spyder, and how to operate an IPython notebook. I recommend taking a look at that material before proceeding.

Open up your chosen text editor and write the following line:

print 5*0.6 - 0.5*9.81*0.6**2

This is a complete Python program for evaluating the formula (2). Save the line to a file with name ball1.py.

The action required to run this program depends on what type of tool you use for running programs:

The output is 1.2342 and appears We remark that there are other ways of running Python programs in the terminal window, see the document Different ways of running Python programs [2].

Suppose you want to evaluate (1) for \( v_0=1 \) and \( t=0.1 \). This is easy: move the cursor to the editor window, edit the program text to

print 1*0.1 - 0.5*9.81*0.1**2

Run the program again in Spyder or re-execute the cell in an IPython notebook. If you use a plain text editor, always remember to save the file after editing it, then move back to the terminal window and run the program as before:

Terminal> python ball1.py
0.05095

The result of the calculation has changed, as expected.

Typesetting of operating system commands. We use the prompt Terminal> in this document to indicate commands in a Unix or DOS/PowerShell terminal window. The text following the Terminal> prompt must be a valid operating system command. You will likely see a different prompt in the terminal window on your machine, perhaps something reflecting your username or the current folder.

Warning about typing program text

Even though a program is just a text, there is one major difference between a text in a program and a text intended to be read by a human. When a human reads a text, she or he is able to understand the message of the text even if the text is not perfectly precise or if there are grammar errors. If our one-line program was expressed as

write 5*0.6 - 0.5*9.81*0.6^2

most humans would interpret write and print as the same thing, and many would also interpret 6^2 as \( 6^2 \). In the Python language, however, write is a grammar error and 6^2 means an operation very different from the exponentiation 6**2. Our communication with a computer through a program must be perfectly precise without a single grammar or logical error. The famous computer scientist Donald Knuth put it this way:

Programming demands significantly higher standard of accuracy. Things don't simply have to make sense to another human being, they must make sense to a computer. Donald Knuth [3] (p. 18), 1938-.
That is, the computer will only do exactly what we tell it to do. Any error in the program, however small, may affect the program. There is a chance that we will never notice it, but most often an error causes the program to stop or produce wrong results. The conclusion is that computers have a much more pedantic attitude to language than what (most) humans have.

Now you understand why any program text must be carefully typed, paying attention to the correctness of every character. If you try out program texts from this document, make sure that you type them in exactly as you see them in the document. Blanks, for instance, are often important in Python, so it is a good habit to always count them and type them in correctly. Any attempt not to follow this advice will cause you frustrations, sweat, and maybe even tears.

Verifying the result

We should always carefully control that the output of a computer program is correct. You will experience that in most of the cases, at least until you are an experienced programmer, the output is wrong, and you have to search for errors. In the present application we can simply use a calculator to control the program. Setting \( t=0.6 \) and \( v_0=5 \) in the formula, the calculator confirms that 1.2342 is the correct solution to our mathematical problem.

Using variables

When we want to evaluate \( y(t) \) for many values of \( t \), we must modify the \( t \) value at two places in our program. Changing another parameter, like \( v_0 \), is in principle straightforward, but in practice it is easy to modify the wrong number. Such modifications would be simpler to perform if we express our formula in terms of variables, i.e., symbols, rather than numerical values. Most programming languages, Python included, have variables similar to the concept of variables in mathematics. This means that we can define v0, g, t, and y as variables in the program, initialize the former three with numerical values, and combine these three variables to the desired right-hand side expression in (1), and assign the result to the variable y.

The alternative version of our program, where we use variables, may be written as this text:

v0 = 5
g = 9.81
t = 0.6
y = v0*t - 0.5*g*t**2
print y

Variables in Python are defined by setting a name (here v0, g, t, or y) equal to a numerical value or an expression involving already defined variables.

Note that this second program is much easier to read because it is closer to the mathematical notation used in the formula (1). The program is also safer to modify, because we clearly see what each number is when there is a name associated with it. In particular, we can change t at one place only (the line t = 0.6) and not two as was required in the previous program.

We store the program text in a file ball2.py. Running the program results in the correct output 1.2342.

Names of variables

Introducing variables with descriptive names, close to those in the mathematical problem we are going to solve, is considered important for the readability and reliability (correctness) of the program. Variable names can contain any lower or upper case letter, the numbers from 0 to 9, and underscore, but the first character cannot be a number. Python distinguishes between upper and lower case, so X is always different from x. Here are a few examples on alternative variable names in the present example:

initial_velocity = 5
acceleration_of_gravity = 9.81
TIME = 0.6
VerticalPositionOfBall = initial_velocity*TIME - \ 
                         0.5*acceleration_of_gravity*TIME**2
print VerticalPositionOfBall

With such long variables names, the code for evaluating the formula becomes so long that we have decided to break it into two lines. This is done by a backslash at the very end of the line (make sure there are no blanks after the backslash!).

In this document we shall adopt the convention that variable names have lower case letters where words are separated by an underscore. Whenever the variable represents a mathematical symbol, we use the symbol or a good approximation to it as variable name. For example, \( y \) in mathematics becomes y in the program, and \( v_0 \) in mathematics becomes v0 in the program. A close resemblance between mathematical symbols in the description of the problem and variables names is important for easy reading of the code and for detecting errors. This principle is illustrated by the code snippet above: even if the long variable names explain well what they represent, checking the correctness of the formula for \( y \) is harder than in the program that employs the variables v0, g, t, and y0.

For all variables where there is no associated precise mathematical description and symbol, one must use descriptive variable names which explain the purpose of the variable. For example, if a problem description introduces the symbol \( D \) for a force due to air resistance, one applies a variable D also in the program. However, if the problem description does not define any symbol for this force, one must apply a descriptive name, such as air_resistance, resistance_force, or drag_force.

How to choose variable names.

Reserved words in Python

Certain words are reserved in Python because they are used to build up the Python language. These reserved words cannot be used as variable names: and, as, assert, break, class, continue, def, del, elif, else, except, False, finally, for, from, global, if, import, in, is, lambda, None, nonlocal, not, or, pass, raise, return, True, try, with, while, and yield. If you wish to use a reserved word as a variable name, it is common to an underscore at the end. For example, if you need a mathematical quantity \( \lambda \) in the program, you may work with lambda_ as variable name. See Exercise 16: Find errors in Python statements for examples on legal and illegal variable names.

Program files can have a freely chosen name, but stay away from names that coincide with keywords or module names in Python. For instance, do not use math.py, time.py, random.py, os.py, sys.py, while.py, for.py, if.py, class.py, or def.py.

Comments

Along with the program statements it is often informative to provide some comments in a natural human language to explain the idea behind the statements. Comments in Python start with the # character, and everything after this character on a line is ignored when the program is run. Here is an example of our program with explanatory comments:

# Program for computing the height of a ball in vertical motion.
v0 = 5    # initial velocity
g = 9.81  # acceleration of gravity
t = 0.6   # time
y = v0*t - 0.5*g*t**2  # vertical position
print y

This program and the initial version in the section Using variables are identical when run on the computer, but for a human the latter is easier to understand because of the comments.

Good comments together with well-chosen variable names are necessary for any program longer than a few lines, because otherwise the program becomes difficult to understand, both for the programmer and others. It requires some practice to write really instructive comments. Never repeat with words what the program statements already clearly express. Use instead comments to provide important information that is not obvious from the code, for example, what mathematical variable names mean, what variables are used for, a quick overview of a set of forthcoming statements, and general ideas behind the problem solving strategy in the code.

Remark

If you use non-English characters in your comments, Python will complain with error messages like

SyntaxError: Non-ASCII character '\xc3' in file ...
but no encoding declared; see
http://www.python.org/peps/pep-0263.html for details

Non-English characters are allowed if you put the following magic line in the program before such characters are used:

# -*- coding: utf-8 -*-

(Yes, this is a comment, but it is not ignored by Python!)

Formatting text and numbers

Instead of just printing the numerical value of y in our introductory program, we now want to write a more informative text, typically something like

At t=0.6 s, the height of the ball is 1.23 m.

where we also have control of the number of digits (here \( y \) is accurate up to centimeters only).

Printf syntax

The output of the type shown above is accomplished by a print statement combined with some technique for formatting the numbers. The oldest and most widely used such technique is known as printf formatting (originating from the function printf in the C programming language). For a newcomer to programming, the syntax of printf formatting may look awkward, but it is quite easy to learn and very convenient and flexible to work with. The printf syntax is used in a lot of other programming languages as well.

The sample output above is produced by this statement using printf syntax:

print 'At t=%g s, the height of the ball is %.2f m.' % (t, y)

Let us explain this line in detail. The print statement prints a string: everything that is enclosed in quotes (either single: ', or double: ") denotes a string in Python. The string above is formatted using printf syntax. This means that the string has various "slots", starting with a percentage sign, here %g and %.2f, where variables in the program can be put in. We have two "slots" in the present case, and consequently two variables must be put into the slots. The relevant syntax is to list the variables inside standard parentheses after the string, separated from the string by a percentage sign. The first variable, t, goes into the first "slot". This "slot" has a format specification %g, where the percentage sign marks the slot and the following character, g, is a format specification. The g format instructs the real number to be written as compactly as possible. The next variable, y, goes into the second "slot". The format specification here is .2f, which means a real number written with two digits after the decimal place. The f in the .2f format stands for float, a short form for floating-point number, which is the term used for a real number on a computer.

For completeness we present the whole program, where text and numbers are mixed in the output:

v0 = 5
g = 9.81
t = 0.6
y = v0*t - 0.5*g*t**2
print 'At t=%g s, the height of the ball is %.2f m.' % (t, y)

The program is found in the file ball_print1.py in the src/formulas folder of the collection of programs associated with this document.

There are many more ways to specify formats. For example, e writes a number in scientific notation, i.e., with a number between 1 and 10 followed by a power of 10, as in \( 1.2432\cdot 10^{-3} \). On a computer such a number is written in the form 1.2432e-03. Capital E in the exponent is also possible, just replace e by E, with the result 1.2432E-03.

For decimal notation we use the letter f, as in %f, and the output number then appears with digits before and/or after a comma, e.g., 0.0012432 instead of 1.2432E-03. With the g format, the output will use scientific notation for large or small numbers and decimal notation otherwise. This format is normally what gives most compact output of a real number. A lower case g leads to lower case e in scientific notation, while upper case G implies E instead of e in the exponent.

One can also specify the format as 10.4f or 14.6E, meaning in the first case that a float is written in decimal notation with four decimals in a field of width equal to 10 characters, and in the second case a float written in scientific notation with six decimals in a field of width 14 characters.

Here is a list of some important printf format specifications (the program printf_demo.py exemplifies many of the constructions):

Format Meaning
%s a string
%d an integer
%0xd an integer in a field of with x, padded with leading zeros
%f decimal notation with six decimals
%e compact scientific notation, e in the exponent
%E compact scientific notation, E in the exponent
%g compact decimal or scientific notation (with e)
%G compact decimal or scientific notation (with E)
%xz format z right-adjusted in a field of width x
%-xz format z left-adjusted in a field of width x
%.yz format z with y decimals
%x.yz format z with y decimals in a field of width x
%% the percentage sign % itself

For a complete specification of the possible printf-style format strings, follow the link from the item printf-style formatting in the index of the Python Standard Library online documentation.

We may try out some formats by writing more numbers to the screen in our program (the corresponding file is ball_print2.py):

v0 = 5
g = 9.81
t = 0.6
y = v0*t - 0.5*g*t**2

print """
At t=%f s, a ball with
initial velocity v0=%.3E m/s
is located at the height %.2f m.
""" % (t, v0, y)

Observe here that we use a triple-quoted string, recognized by starting and ending with three single or double quotes: ''' or """. Triple-quoted strings are used for text that spans several lines.

In the print statement above, we print t in the f format, which by default implies six decimals; v0 is written in the .3E format, which implies three decimals and the number spans as narrow field as possible; and y is written with two decimals in decimal notation in as narrow field as possible. The output becomes

Terminal> python ball_print2.py

At t=0.600000 s, a ball with
initial velocity v0=5.000E+00 m/s
is located at the height 1.23 m.

You should look at each number in the output and check the formatting in detail.

Format string syntax

Python offers all the functionality of the printf format and much more through a different syntax, often known as format string syntax. Let us illustrate this syntax on the one-line output previously used to show the printf construction. The corresponding format string syntax reads

print 'At t={t:g} s, the height of the ball is {y:.2f} m.'.format(
      t=t, y=y)

The "slots" where variables are inserted are now recognized by curly braces rather than a percentage sign. The name of the variable is listed with an optional colon and format specifier of the same kind as was used for the printf format. The various variables and their values must be listed at the end as shown. This time the "slots" have names so the sequence of variables is not important.

The multi-line example is written as follows in this alternative format:

print """
At t={t:f} s, a ball with
initial velocity v0={v0:.3E} m/s
is located at the height {y:.2f} m.
""".format(t=t, v0=v0, y=y)

The newline character

We often want a computer program to write out text that spans several lines. In the last example we obtained such output by triple-quoted strings. We could also use ordinary single-quoted strings and a special character for indicating where line breaks should occur. This special character reads \n, i.e., a backslash followed by the letter n. The two print statements

print """y(t) is
the position of
our ball."""

print 'y(t) is\nthe position of\nour ball'

result in identical output:

y(t) is
the position of
our ball.