This notebook works through the use of Python at the level of a calculator, with attention paid to common mathematical operations. We also briefly discuss the use of the math library, variables, types, type conversion, and printing.

Together with this, you should read Chapter 1 of

*Programming for Computations - Python: A Gentle Introduction to Numerical Simulations with Python 3.6*by Svein Linge and Hans Petter Langtangen, 2nd edition.

You can use Python as a calculator to get comfortable working with numbers in Python. Here are some examples.

In [1]:

```
5+3
```

Out[1]:

In [2]:

```
35 * 45
```

Out[2]:

In [3]:

```
1 / 3
```

Out[3]:

In [4]:

```
2 * (3 + 4)
```

Out[4]:

Exponentiation is denoted with the `**`

operator. (The symbol `^`

is reserved for bitwise exclusive or.)

In [5]:

```
2**3
```

Out[5]:

In [6]:

```
2^3
```

Out[6]:

The number 52 divided by 3 is 17 with a remainder of 1. Python can compute 17 and 1 with the `//`

and `%`

operators.

In [7]:

```
52 // 3
```

Out[7]:

In [8]:

```
52 % 3
```

Out[8]:

Note that `a // b`

always returns the greatest integer less than or equal to $\frac{a}{b}$. This is important for how answers are returned for negative numbers. Also if `a // b`

is $c$ and `a % b`

is $d$, then we have $a = b*c + d$. This explains the following output:

In [9]:

```
-52 // 3
```

Out[9]:

In [10]:

```
-52 % 3
```

Out[10]:

In [11]:

```
-52 // -3
```

Out[11]:

In [12]:

```
-52 % -3
```

Out[12]:

You can also test compare numbers with `==`

, `!=`

, `<`

, `>`

, `<=`

and `>=`

. These represent the mathematical relations $=$, $\neq$, $<$, $>$, $\leq$ and $\geq$ respectively.

In [13]:

```
3 == 5
```

Out[13]:

In [14]:

```
2**3 == 8
```

Out[14]:

In [15]:

```
2 < 3
```

Out[15]:

In [16]:

```
4 <= 3
```

Out[16]:

In [17]:

```
1 != 2 / 2
```

Out[17]:

In [18]:

```
1/3 == 0.3333
```

Out[18]:

In [19]:

```
1/3 == 0.333333333333333333333333
```

Out[19]:

`math`

library¶The math library contains numerous useful mathematical functions, which are listed in the Python documentation for the `math`

library.

Trigonometry is done in radians. For example, to compute $\cos \frac{\pi}{4}$, you might do the following:

In [20]:

```
from math import pi, cos
cos(pi/4)
```

Out[20]:

The line `from math import pi, cos`

allows us to use the `pi`

constant and the `cos`

function from the library. Once this is done, we can continue to use these in the rest of the file.

In [21]:

```
cos(-2*pi/6)
```

Out[21]:

Note that we didn't import the `sin`

function so typing `sin(pi/6)`

would result in an error as depicted below:
We can solve this problem by importing `sin`

as well.

In [22]:

```
from math import sin
sin(pi/6)
```

Out[22]:

You can import a whole library, as demonstrated below.

In [23]:

```
import math
```

When you import the whole library math as above you need to write `math.something`

to access the `something`

in the math library. For example

In [24]:

```
math.tan(math.pi/4)
```

Out[24]:

In [25]:

```
math.e
```

Out[25]:

A good thing about doing this is you can learn about the math library by playing around. For example typing `math.`

followed by pressing the Tab button will lead to a list of objects in the math library. When I do this, I get the following popup list.

See if you can also get this list to appear, and scroll through it.

Python also has self contained documentation. For example, you might wonder what the `atan2`

function does. Typing `math.atan2?`

and pressing Shift+Return produces the documentation. Try it.

In [26]:

```
math.atan2?
```

You can also see the documentation of things imported in the other way with something like `cos?`

.

You can also import math with a different name. This is often used to simplify a library name or to avoid name clashes. For example the following imports the `math`

library with the name `m`

and does a simple calculation.

In [27]:

```
import math as m
m.exp(2)
```

Out[27]:

For more information on importing see §1.4 of *Programming for Computations - Python* by Svein Linge and Hans Petter Langtangen, 2nd edition.

Variables can be assigned values with the `=`

operator.

In [28]:

```
x = 3
```

The variable keeps the same value until it is changed by the program. For example, the following line prints the value of `x`

.

In [29]:

```
print(x)
```

This can also be accomplished with the following, because by default Jupyter prints the value produced at the end of a code cell.

In [30]:

```
x
```

Out[30]:

In math the statement `x=x+1`

is always False (assuming `x`

is a real number). In Python, it means that the program should first compute the value of `x+1`

and then store it in the variable `x`

. This results in `4`

being stored in `x`

.

In [31]:

```
x = x+1
print(x)
```

Note that variables can store more than just numbers. Here, we store and add two strings (which concatenates).

In [32]:

```
s1 = "We are using "
s2 = "Python to compute."
print(s1+s2)
```

Here we store a 4-tuple in v.

In [33]:

```
v = (1,2,3,4)
print(v)
```

That `v`

is a tuple can be determined using the `type`

function.

In [34]:

```
type(v)
```

Out[34]:

Also the length (or number of elements) in the tuple can be found using the `len`

function.

In [35]:

```
len(v)
```

Out[35]:

You can access the individual entries using the form `v[i]`

where `i`

runs from zero up through one less than the number of entries in `v`

. For example the 4th entry can be obtained by:

In [36]:

```
v[3]
```

Out[36]:

Tuples are not vectors in the sense that algebraic operations mean something different. For example, `3*v`

is three copies of `v`

concatenated.

In [37]:

```
3*v
```

Out[37]:

Addition concatenates. For example:

In [38]:

```
v + (5, 6)
```

Out[38]:

You have probably noticed that there are at least two different types of numbers: integers and floating point numbers. You can determine the type of a number `x`

with `type(x)`

. For example:

In [1]:

```
a = 3
type(a)
```

Out[1]:

In [2]:

```
x = 4/3
type(x)
```

Out[2]:

In [3]:

```
type('Hello!')
```

Out[3]:

Many natural conversions between types are built in functions. For example to convert from an integer to a float, you use:

In [7]:

```
float(2)
```

Out[7]:

You can also go the other way.

In [8]:

```
int(3.0)
```

Out[8]:

You can use `str(x)`

to convert `x`

to a string. This together with the `+`

operator for string concatenation is a useful way of displaying variable values. For example:

In [16]:

```
import math
theta = math.pi/5
'tan(' + str(theta) + ') = ' + str(math.tan(theta))
```

Out[16]:

Using concatenation to form strings makes reading the code difficult. Python has some built in ways to make this process easier and more efficient.

An equivalent to construct the string above line is given below:

In [17]:

```
'tan({}) = {}'.format(theta, math.tan(theta))
```

Out[17]:

The above command works because strings have a format method. Basically, the format method looks for instances of `{}`

and replaces these curly brackets with string representations of arguments passed the the format method. In the above example we have two curly brackets and two parameters (`theta`

and `math.tan(theta)`

). The parameters are converted to strings and used to replace the curly brackets.

The format syntax is pretty powerful, but for now we will be content with basic useage. Section 1.6.2 of LL goes into more detail, including a discussion of formatting numbers.

If you are interested in learning more, concentrate on looking at the examples in the Python documentation of the format string syntax.

Another option for formatting is to use f-strings. We can format the same string with the following:

In [19]:

```
f'tan({theta}) = {math.tan(theta)}'
```

Out[19]:

You can tell this is an f-string because the string has an `f`

in front. The f-string is automatically converted to a string by replacing `{theta}`

with `str(theta)`

and `{math.tan(theta)}`

with `str({math.tan(theta)})`

.

You can learn more about f-strings from PEP 498 -- Literal String Interpolation.

You might have noticed that Jupyter only prints the results from the last line executed. So for example, `3`

is not printed below even though $3 = 1+2$.

In [21]:

```
1+2
3+4
```

Out[21]:

The simple fix for this is to use the print statement if you want to see an intermediate value:

In [23]:

```
print(1+2)
3+4
```

Out[23]:

Here, `3`

is computed as $1+2$, and then converted to a string and displayed by Jupyter.

This sort of printing is very useful for debugging. For example, below we have attempted an implementation of the quadratic formula to find the roots of $$(2 x-1)(x-2)=2 x^2 - 5x +2.$$ (From the factorization above, you can see that the roots should be $1/2$ and $2$.)

In [28]:

```
a = 2 # coefficient of x^2
b = -5 # coefficient of x
c = 2 # constant coefficient
q = math.sqrt(b*b - 4*a*c)
root1 = (-b + q)/2*a
root2 = (-b - q)/2*a
print(f'The roots are {root1} and {root2}.')
```

So, there is some error in our code. To debug you might check that the value of $q = \sqrt{b^2-4ac}$ is correct. In our example this should be $\sqrt{25-16}=3.$ Let's check our code:

In [29]:

```
a = 2 # coefficient of x^2
b = -5 # coefficient of x
c = 2 # constant coefficient
q = math.sqrt(b*b - 4*a*c)
print(f'q = {q}')
root1 = (-b + q)/2*a
root2 = (-b - q)/2*a
print(f'The roots are {root1} and {root2}.')
```

Well the value of $q$ is correct, so the problem must be in the formulas for `root1`

and `root2`

. *Ah...* Multiplication and division have the same precidence and so the code is computing $-b+q$, dividing it by $2$ and then multiplying the result by $a$. We really want to divide by $2a$. So, a fix is below:

In [30]:

```
a = 2 # coefficient of x^2
b = -5 # coefficient of x
c = 2 # constant coefficient
q = math.sqrt(b*b - 4*a*c)
print(f'q = {q}')
root1 = (-b + q)/(2*a)
root2 = (-b - q)/(2*a)
print(f'The roots are {root1} and {root2}.')
```

Anyway, the point I want to make is that printing intermediate values can allow you to zoom in on the problematic lines in code with errors.