AP20005 Programming in Physics (using the Python Programming Language)

# AP20005 Programming in Physics (using the Python Programming Language)

Online Python Programming websites: (1) OnlineGDB, (2) CodingGround, (3) Rex Tester (4) Google Colab
ONLINE Computer Laboratory and Assignment Schedule
 Group 2 Group 1 Time Tue 1:30 - 4:20 Wed 1:30 4:20 Assignment due date Tutor Lab 1 9 Feb 10 Feb 24 Feb Anakin Lab 2 2 Mar 3 Mar 10 Mar Udoka Lab 3 16 Mar 17 Mar 24 Mar Udoka Lab 4 30 Mar 31 Mar 14 Apr Udoka Lab 5 20 Apr 21 Apr - Anakin Test 25 Mar 25 Mar Anakin
Assignments / Solutions

# Contents

1  Overview of Computers
1.1  History of Computers
1.2  Programming Languages
1.3  Software Library
2  Overview of Python
2.1  The simplest Python program
2.2  Execute Python Program Online
2.3  Mathematical operations
2.4  Comments in a program
2.5  Using variables
2.6  If and else
2.7  While loop
2.8  Debugging approaches
3  Computer Fundamentals
3.1  Bits and Bytes
3.2  Binary and hexadecimal numbers
3.3  Digital information
3.4  Computer Architecture
3.5  Low level programming language
3.6  High level programming language
4  Python variables and simple data types
4.1  Variables and identifiers
4.2  Integers
4.3  Floating point number
4.4  Boolean
4.5  Character and String
5  Operators and Expressions
5.1  Assignment operator (=)
5.2  Arithmetic operators (+, - ,* , / , **, %)
5.3  Compound assignment( +=, -=, *=, /=, **=, %= )
5.4  Equality and Relational operators ( ==, !=, >, <, >=, <= )
5.5  Logical operators ( and, or, not )
5.6  Precedence of operators
6  List and Range
6.1  List of numbers
6.2  List of variables of mixed types
6.3  Modifying elements in a list
6.4  Range
7  Program control statements
7.1  If, else, elif
7.2  While loop
7.3  For loop
7.4  Nested loops
8  Functions
8.1  Function Definition and Usage
8.2  Arguments of functions
8.3  Returned value of function
8.4  Returning multiple values
8.5  Mathematical Functions
9  Jupyter Notebook and Google Colab
10  Strings and Input / Output
10.1  Escape sequence
10.2  String operations
10.3  Formatted strings
10.4  Input
10.5  File Output
10.6  File Input
11  Python Libraries
11.1  Introduction
11.2  NumPy
11.3  Matplotlib
12  Advanced topic: Classes
Website: http://apricot.ap.polyu.edu.hk/pip   (for access outside our Lab, use login: ep password: ep)
Lecturer: Dr. C.H. Lam (Office: BC615, Tel: 2766-5681)
Tutor (Lab + Grading): Mr. Anakin, Lee Chun Shing (Email: cs.lee@connect.polyu.hk     Office: BC521)
Tutor (Lab + Grading): Mr. Udoka NWANKWO (Email: 18045211r@connect.polyu.hk)
Learning Outcomes and Syllabus: AP20005
Textbooks:
Reference books:
• A. Scopatz and K.D. Huff, Effective Computation in Physics: Field Guide to Research with Python, O Reilly Media (2015).
• J Zelle, Python Programming: an Introduction to Computer Science, 3rd Edition, Franklin, Beedle & Associates (2016).
Assessment: Assignments and Tests (40%), Examination (60%)
Python Websites / Software:

# Chapter 1 Overview of Computers

## 1.1  History of Computers 1946: The first computer - ENIAC (Electronic Numerical Integrator And Computer) in the US Amry using vacuum tubes 1960s - 1970s: Mainframe computers based on transitors or integrated circuits, e.g. IBM 7090 1960s - 1970s: Mini-computers, e.g. PDP-7 1971: first micro-processor - Intel 4004 1976: Cray-1 supercomputer 1981: IBM Personal Computer (PC) with Intel 8088 miro-processor 1990s: Workstation, e.g. Sun SPARCstation 2000s: Workstation Clusters, e.g. SGI Altix cluster at NASA 2000s: PC Clusters 2010s: GPU (Graphic Processing Unit) computing 2010s: High performance computing, e.g. Sunway supercomputer
Moore's law : The number of transistors in a computer's Central Processing Unit (CPU) roughly doubles very year.

## 1.2  Programming Languages

Computer softwares are written by human using programming languages.
Popularity of Programming Languagues based on a survey in 2016:
```1	Java                    21.465%
2	C                       16.036%
3	C++                     6.914%
4	C#                      4.707%
5	Python                  3.854%
6	PHP                     2.706%
7	Visual Basic .NET       2.582%
8	JavaScript              2.565%
9	Assembly language       2.095%
10	Ruby                    2.047%
11	Perl                    1.841%
12	Delphi/Object Pascal	1.786%
13	Visual Basic            1.684%
14	Swift                   1.363%
15	MATLAB                  1.228%
16	Pascal                  1.194%
17	Groovy                  1.182%
18	Objective-C             1.074%
19	R                       1.054%
20	PL/SQL              	1.016%
...

```
Python programming language:
Advantage:
• It is roughly 5 times faster to develop programs in Python than in C++.
• Python handles many complications of computer internal operations. You do have to worry about them. So, learning is also fast.
Disadvantage:
• It is roughly 10 - 100 times slower for a Python program to run compared with a C++ program.
• Python handles many complications of computer internal operations. You would not learn much about them by learning python. For advanced programming, learn C++ too.
Programming languages I have used (in descend order of experience):
C, C++, Matlab, Assembly-8080, Assembly-6502, Pascal, Perl, Basic, Java, Maple, Python, csh, Fortran, PHP.

## 1.3  Software Library

A software library is a collection of programs which you can include into your own program to create the final software. A popular example is Google's artificial intelligence software library called TensorFlow:
• To use Tensorflow, we need to program in Python (i.e. highly convenient to program)
• To develop TensorFlow, Google uses C++ and NVIDIA's CUDA (i.e. highly efficient to run)

# Chapter 2 Overview of Python

## 2.1  The simplest Python program

Below is the Python source code in a file "simple.py" which calculates 12 ×14.
simple.py
```print (12*14)
```
Execution of the program gives the answer 168.
Explanation
12*14
an expression for 12 ×14. Multiplication is represented by the operator *.
print ( ... )
Python function for printing to the computer screen

## 2.2  Execute Python Program Online

The OnlineGDB website includes an Integrated Development Environment (IDE), which is a software assisting the development of Python.
To execute our program:
1. Using a web browser (e.g. firefox or internet explorer), enter the CodingGround website at OnlineGDB.
2. In the main.py window in the middle, erase the original program and type our Python program source codes.
3. Click Run. The answer 168 should appear in the output window in the bottom.
Alternatively, you can use other websites listed on the top of this webpage.

## 2.3  Mathematical operations

Built-in mathematical operations, e.g. +, -, *, /, and also ** (i.e. raise to the power).
Example:
Calculate √5, i.e. square root of 5
power.py
```print ( 5 ** 0.5 )
```
( power.py )
Execution of the program gives the answer 2.23606797749979.
Explanation
Operator **
x**y gives x raised to the power y
5
an integer
0.5
a floating point number, i.e. non-integer

Math library functions: sin, cos, sqrt, exp, log, etc.
root.py
```from math import *
print ( sqrt(5) )
```
( root.py )
Explanation
from math import *
Load all functions from the math library for future use.
sqrt( ... )
square root function, which comes with the math library
Library functions expand basic capabilities of python.

## 2.4  Comments in a program

Explanations about a program can be put as comments, e.g.
root2.py
```""" root2.py
To compute the root of 5
written for Programming in Physics """

# import library
from math import *

# main program
print ( sqrt(5) )  # calculate square root
```
( root2.py )
Explanation
"""
3 double-quotes mark the beginning and end of a multi-line comment
#
Hash sign marks the rest of the line as a comment
Comments improves readability of a program. Better readability implies
• easier to understand
• easier to debug (i.e. remove errors)
• easier to modify or improve (i.e. easier maintainence)

## 2.5  Using variables

Example: Quadratic equation
Solve the equation
 ax2+bx+c=0
(2.1)
for a=1, b=3 and c=−4.
The solution
x=
 −b ± √ b2 − 4 a c

2a
(2.2)
can be computed using
quadratic1.py
```# Solving ax^2 + bx + c = 0 for a=1, b=3, c=-4
from math import *

print ( (-3 + sqrt(3*3 -4*1*(-4))) / (2*1) )
print ( (-3 - sqrt(3*3 -4*1*(-4))) / (2*1) )
```
It outputs:
1.0
-4.0
Using variables, it can be improved to:
quadratic2.py
```# Solving ax^2 + bx + c = 0 for a=1, b=3, c=-4
from math import *

a = 1
b = 3
c = -4
print ( (-b + sqrt(b**2 -4*a*c)) / (2*a) )
print ( (-b - sqrt(b**2 -4*a*c)) / (2*a) )
```
Explanation
Variable
Variable are referred to by names, e.g. a, b, c
Assignment statement
A variable can be assigned a value using the assignment operator '='. Further assignments overwrite old values.
Advantages of quadratic2.py
• the Python code (-b + sqrt(b*b-4*ac*))/(2*a) is directly related to Eq. (2.2), implying better readability
• easier to modify the program for other problems, e.g. 2x2 + 3x −4=0

Introducing the determinant
 D=b2 − 4 a c
(2.3)

 x= −b ±√D 2a
(2.4)
the program can be alternatively written as
quadratic3.py
```# Solving ax^2 + bx + c = 0 for a=1, b=3, c=-4
from math import *

a = 1
b = 3
c = -4
D = b**2 -4*a*c # determinant

x1 = (-b + sqrt(D)) / (2*a) # 1st root
x2 = (-b - sqrt(D)) / (2*a) # 2nd root
print ( x1, x2)
```
It outputs: 1.0 -4.0

## 2.6  If and else

For a quadratic equation, solutions exist only under certain condition, i.e
If determinant D ≥ 0, solutions are given by Eq. (2.4)
This can be implemented using an if statement:
quadratic-if.py
```# Solving ax^2 + bx + c = 0
from math import *

a = 1
b = 3
c = -4
D = b*b-4*a*c # determinant

if D >= 0:
# indented lines below executed only if expression is true
x1 = (-b + sqrt(D)) / (2*a) # 1st root
x2 = (-b - sqrt(D)) / (2*a) # 2nd root
print (x1, x2)
print ("End of execution")
```
It outputs:
1.0 -4.0
End of execution
Explanation
• The "if" command decides whether the following indented lines will be executed or skipped.
• Indented lines are shifted 4 spaces to the right.
• Double quotes (".. ") enclose a character string, i.e. a sequence of characters.
The syntax of the if statement is
Syntax
```if <condition>:
statement

```
Alternatively, we can say:
If determinant D ≥ 0, solutions are given by Eq. (2.4), else no solution exists.
This can be implemented using an if-else statement:
quadratic-if2.py
```# Solving ax^2 + bx + c = 0
from math import *

a = 1
b = 3
c = -4
D = b*b-4*a*c # determinant

if D >= 0:
# indented lines below executed only if expression is true
x1 = (-b + sqrt(D)) / (2*a) # 1st root
x2 = (-b - sqrt(D)) / (2*a) # 2nd root
print (x1, x2)
else:
print ( "no solution" )
```
Syntax
```if <condition>:
statement
else:
statement

```

## 2.7  While loop

Very often, we have to repeat similar actions many times, e.g. outputting 0,1,2, .. N−1 to the screen. The following program uses a direct approach for N=5:
noloop.py
```print (0)
print (1)
print (2)
print (3)
print (4)
```
However, for large N, it is tedious to type in the program. The following version is slightly better because it can be entered by simple copy and paste actions:
noloop2.py
```i = 0

print (i)  # i = 0
i = i+1

print (i)  # i = 1
i = i+1

print (i)  # i = 2
i = i+1

print (i)  # i = 3
i = i+1

print (i)  # i = 4
i = i+1
```
Explanation
i = i+1
assign the value of i+1 to the variable i,    i.e. i ← i+1. For example, if i is initially 0, after execution, i becomes 1.
Observing that the same statement "print (i); i = i+1" is repeated 5 times, we can instead use a loop construction, e.g. the while loop:
whileloop.py
```i = 0;
while i < 5:
print (i)
i = i+1
```
Explanation
while
the indented statements below will be executed repeatedly while the condition is true.
Syntax
```while <condition>:
statement

```
Tracing a program (i.e. running a program line-by-line)
Using OnlineGDB, type in the whileloop.py program. Then,
1. to start line-by-line program execution, click "Debug"
2. to execute one line of the program, click "step over".
3. look at the value of the variable "i" under "Local Variables" on the right panel. See it changes as you click "step over" a few times.
Advantages of Looping
• the only means for repeatedly executing codes many times (e.g. 1010 times)
• the codes to be repeated and the number of repetitions can be modified easily
• more readable because the repetition is stated explicitly
Calculate the factorial n! of n defined by
 n! = 1 ×2 ×3 .... ×n
(2.5)
The following program uses a direct approach
factorial1.py
```# direct approach to calculate 5! (factorial of 5)
x = 1 * 2 * 3 * 4 * 5
print (x)
```
which can be improved to
factorial1a.py
```x = 1

i = 1; x = x * i # x=1
i = 2; x = x * i # x=1.2
i = 3; x = x * i # x=1.2.3
i = 4; x = x * i # x=1.2.3.4
i = 5; x = x * i # x=1.2.3.4.5

print (x)
```
where ";" allows us to put more than one command in a single line. It can be further improved to
factorial2.py
```x = 1
i = 1

x = x * i; i = i + 1 # x=1  i=2
x = x * i; i = i + 1 # x=1.2  i=3
x = x * i; i = i + 1 # x=1.2.3  i=4
x = x * i; i = i + 1 # x=1.2.3.4  i=5
x = x * i; i = i + 1 # x=1.2.3.4.5  i=6

print (x)
```
A better way is to use the while loop:
factorial-loop.py
```# using while-loop to calculate n! (factorial of n)
n = 5
x = 1
i = 1
while i <= n:
x = x * i
i = i + 1
print (x)
```

## 2.8  Debugging approaches

Bugs and debugging
Mistakes in computer source codes are called bugs. The process of identifying and correcting the bugs is called debugging.
Types of bugs
Syntax errors (i.e. compiler errors, or build errors):
The grammatic rules of Python is not followed, e.g. use of unassigned variable, errors due to a missing colon, etc. (Easy)
Logical errors:
The program can be compiled and executed. However, due to logical or mathematical mistakes in the program, the results are incorrect. (Difficult!)
Logical errors
• Can be difficult and time consuming to debug! Be patient! Don't despair! Don't blame your computer!
• Good programming practices can minimize logical errors.
For example, the program below trys to calculate 5! but outputs 8 instead. Why?
factorial-bug.py
```# using while-loop to calculate n! (factorial of n)
n = 5
x = 1
i = 1
while i <= n:
x = x * i
i = i + i
print (x)
```
Common debugging approaches for logical errors
1. Inspection, i.e. read the source code many times carefully
2. Dry running, i.e. imitating the execution by doing the calculations by hand
3. Outputting intermediate values of the variables to obtain more clues
4. Tracing the execution and examining intermediate variables using a debugger to obtain more clues
5. Last resort: forget your buggy program. Start all over again
Outputting intermediate values
For example, statements for outputting intermediate values are added for debugging purpose:
factorial-debug.py
```# using while-loop to calculate n! (factorial of n)
n = 5
x = 1
i = 1
while i <= n:
x = x * i
print ("x = ", x) # debugging
i = i + i
print ("i = ", i) # debugging
print (x)
```

# Chapter 3 Computer Fundamentals

## 3.1  Bits and Bytes

A bit of storage can be either 0 or 1.
1 Byte = 8 bits
Many bits and bytes can be stored in, e.g.:
• Random Access Memory (RAM): The diagram below shows 16 cells of Dynamics Random Access Memory (DRAM). A cell consists of a capacitor and a transistor and stores one bit of information, e.g. a charged (uncharged) capacitor state represents 1 (0).
• Magnetic Hard-disk: e.g. a small magnetized (unmagnetized) region represents 1 (0).

## 3.2  Binary and hexadecimal numbers

Decimal number (base 10)
Allowed digits: 0,1,2,3,4,5,6,7,8,9
e.g.   5123 = 5 ×103 + 1 ×102 + 2 ×101 + 3
Each digit requires 4 bits to store (non-optimal efficiency)
Binary number (base 2)
Allowed digits: 0,1
e.g.   1101 = 1 ×23 +1 ×22 + 0 ×21 + 1
Each digit requires 1 bit to store
Hexadecimal (base 16)
Allowed digits: 0,1,2,3,4,5,6,7,8,9,A,B,C,D,E,F
e.g.   2F8A = 2 ×163 + 15 ×162 + 8 ×16 + 10
Each digit requires 4 bits to store
```hexadecimal decimal      binary

0          0           0000
1          1           0001
2          2           0010
3          3           0011
4          4           0100
5          5           0101
6          6           0110
7          7           0111
8          8           1000
9          9           1001
A          10          1010
B          11          1011
C          12          1100
D          13          1101
E          14          1110
F          15          1111

```
One byte (8 bits) can store one of the following
• 8 digits long binary number: 00000000 ... 11111111 (i.e. in decimal 0 ... 255) [fundamental format]
• 2 digits long hexadecimal number: 00 ... FF (i.e. in decimal 0 ... 255) [more readable than binary]
• 2 digits long decimal number: 00 .. 99 [packed decimals, rarely used]

## 3.3  Digital information

 1 Byte
 = 8 bits
 1 KB
 = 1 Kilo−byte = 1024 bytes ≅ 103 bytes
 1 MB
 = 1 Mega−byte = (1024)2 bytes ≅ 106 bytes
 1 GB
 = 1 Giga−byte = (1024)3 bytes ≅ 109 bytes
 1 TB
 = 1 Tera−byte = (1024)4 bytes ≅ 1012 bytes
Examples of digital information
• number: a few bytes
• a text-based e-mail: a few hundred Bytes
• source codes of a short program: a few KBs
• a book: a few MBs
• a photograph: a few MBs
• a movie: a few GBs

## 3.4  Computer Architecture

The inside of a typical desktop computer:
The most important components of a computer include
• Central Processing Unit (CPU) to execute arithmetical and logical operations
• Random Access Memory (RAM) to temporally store data needed in its operations.
• Input/Output (I/O) Devices such as harddisk, keyboard, mouse, graphic display, network adaptor, etc.
A simple CPU consists of
• Arithmetic Logic Unit (ALU) to execute arithmetical and logical operations
• Control Unit (CU) to control all operations within the CPU, e.g. retrieving commands stored in memory, decoding them and asking the ALU to execute them
• Registers to temporarily store data to support CPU operations
A typical Personal Computer Specification:
Processor
AMD Ryzen 7 5800X CPU, 8 cores, 36MB Cache, base frequency 3.8GHz    (i.e. 8 CPU's packed into one chip; 36MB fast memory inside CPU; 3.8 ×109 operations per second)
Main Memory
2 x Kingston Hyper X DDR4 3600MHz 16GB RAM (Total 32GB)
Hard Drive
Micron Crucial CT1000P5SSD8 1TB M.2 SSD
Video Card
Asus GT710-4H-SL-2GD5 2GB Display Card (4 x HDMI) 192 cores

## 3.5  Low level programming language

A CPU can only directly execute Machine Language / Machine Codes, e.g.
...
48 89 32
...
which represents a 3-bytes command (in hexadecimal). This command can be written in Assembly Language source code as
...
movq %rsi, (%rdx)
...
which means moving an 8-byte value from memory address pointed to by the data register to the source index register.
• Programmers write assembly language source codes and convert them into machine codes using a software called an assembler.
• Any possible machine codes can be produced by some assembly language source codes. Therefore, assembly language can do anything the CPU can do.
• In Windows Operating System, an executable file ( .exe file) contains machine code.
• Different CPU's in general uses different machine codes / assembly languages, i.e. poor portability

## 3.6  High level programming language

Compiled languages: C/C++, Java, Fortran, Pascal, Basic, Matlab, ...
For C++,
• C++ source codes of a whole program are converted into machine codes using a software called a C++ compiler and is stored in an executable file ( e.g. .exe file )
• User then run the executable file.
• Advantage: the executable usually runs very fast.
Interpreted languages: Python, Perl, Basic, Matlab, ...
For Python,
• Python source code is interpreted line-by-line by a software called a Python Interpreter, i.e. the interpreter read a python command, executes corresponding machine codes, and move to the next line.
• Advantage: convenient to use (no need to compile, no extra compiled file).
• Disadvantage: 10 - 100 times slower, e.g. a python command in a loop will be interpreted from scratch every time execution enters the loop.
Typical program development time
Assembly : C++ : Python = 100 : 5 : 1
Typical program execution time
Assembly : C++ : Python = 1 : 2 : 40

# Chapter 4 Python variables and simple data types

## 4.1  Variables and identifiers

A variable consists of a number of bytes in computer memory for storing data. Each variable stores data of a specific data type, e.g. integer, floating-point number, etc.
An identifier is a name used to describe variables, functions, or other items.
An identifier of a variable is the variable name.
An identifier
• must begin with a letter (A-Z,a-z) or underscore ( _ ).
• can be followed by letters, digits (0-9), or underscore
• are case sensitive, e.g. "x=1; X=2" creates 2 different variables.
• must not be a reserved word
Python reserved words, also called keywords, are:
False, class, finally, is, return, none, continue, for, lambda, try, True, def, from, nonlocal, while, and, del, global, not, with, as, elif, if, or, yield, assert, else, import, pass, break, except, in, raise.

## 4.2  Integers

Unsigned integer
1 bit:   stores 0 or 1
8 bits ≡ 1 byte:   store 0, 1, ... , or 255      (i.e. 0, ... , 28 - 1)
32 bits ≡ 4 byte:   store 0, 1, ... , or 4294967295      (i.e. 0, ... , 232 - 1)

integer (i.e. signed integer)
8 bits ≡ 1 byte:   store -128, -127, ... , or 127      (i.e. 28 possibilities)
32 bits ≡ 4 byte:   store -2147483648, ... , or 2147483647      (i.e. 232 possibilities; used by most CPU's)

Python integer data type: int
integer.py
```x1 = 5
x2 = 3*2
x3 = 5/4        # float point division
x4 = 8/4        # float point division
x5 = 7%4        # remainder
x6 = int(2.6)   # type conversion, truncating to integer
x7 = round(2.6) # round up to integer
x8 = 2**100     # a very large integer
print( x1, x2, x3, x4 )
print( x5, x6, x7, x8 )
print( type(5) )  # output data type of a value
print( type(x1), type(x3), type(x4) ) # output data type of variables
```
Program output:
5 6 1.25 2.0
3 2 3 1267650600228229401496703205376
<class 'int'>
<class 'int'> <class 'float'> <class 'float'>
Explanation
• All data in Python has a type, e.g. integer (int), floating point number (float)
• The type() function tells the data type ('class' means object type).
• The int() function performs a type conversion, e.g. from float. Digits behind the decimal points are truncated.
• The round() performs a round up.
• The value can be arbitrarily large, and is exact.
 Type Description Storage size Allowed values int integer variable: larger number needs more bits −∞  ...   ∞
i.e. arbitrary-precision integer arithmetics
• Built on 32-bit integers
• Advantage: convenient
• Disadvantage: very slow (because not natively supported by CPU)
• Most computer languages use 32-bits integers

## 4.3  Floating point number

A double-precision floating point number has 64 bits and is expressed as
 x = (−1)s ×m ×2e−1023
(4.1)
Explanation
s   (1 bit)
Sign bit, s = 0 or 1
e   (11 bits)
Exponent, e = 0 .. 2047
m   (52 bits)
Significand (in binary), m = 1. b1 b2 b3 ... b51,     i.e. from 1.0000000000000000000000000000000000000000000000000000 to 1.1111111111111111111111111111111111111111111111111111
Example: double-precision floating point number
A double precision floating point number x is represented by s=1, e=1026 (in decimal), and m=1.1101 (in binary). Calculate x in decimal form.
Answer:
 m
 =
 1 + 1/2 + 1/4 + 0/8 + 1/16 = 1.8125
 x
 =
 (−1)1 ×1.8125 ×21026−1023 = −14.5
• The maximum expressible value (overflow threshold) is about xmax=21024. Overflow Error occurs when a value is outside [−xmax, xmax]. Then, 'inf' (i.e. infinity) may result or program may stop.
• The minimum non-zero expressible value (underflow threshold) is about xmin=2−1022. Underflow occurs when a value is within [−xmin, xmin]. Then, 0 results.
• Floating point numbers have finite precisions. Further digits are automatically rounded off.
• The machine epsilon (machine precision) ϵ is the smallest value so that 1+ϵ is not rounded off to 1. Here, ϵ ≅ 2−53 ≅ 1.11 ×10−16
Typical properties of single and double precision floating point numbers are
 Type Precision Storage Machine epsilon Overflow threshold Underflow threshold float Double 8 bytes at least (24 bytes) 2−53 ≈ 1.11×10−16 21024 ≈ 1.79×10308 2−1022 ≈ 2.23×10−308
float.py
```x1 = 6.022e23         # floating point constant assigned to x1
x2 = 1e300 * 1e100  # overflow -> inf.
x3 = 1e-300 / 1e100 # underflow -> 0
x4 = 1 + 1e-15       # -> 1.000000000000001
x5 = 1 + 1e-16       # -> 1.0  (why not 1.0000000000000001 ?)
x6 = (1 + 0.1) -1    # -> 0.10000000000000009  (why not 0.1 ?)
print(x1, x2, x3, x4, x5, x6)
```
( float.py )
Program output:
6.022e+23 inf 0.0 1.000000000000001 1.0 0.10000000000000009
Explanation
• 6.022e23 denotes the scientific notation 6.022×1023
• Only numbers within 16 significant figures are accurately handled. Otherwise, machine epsilon becomes important and you get machine errors.

## 4.4  Boolean

The data type for a boolean value is
 Type Description Storage size possible values bool Boolean 1 bit at least (24 bytes) True ≡ 1, False ≡ 0
boolean.py
```x = 3 < 4
print( 3 > 4, x, x+1, type(x) )
```
Program output:
False True 2 <class 'bool'>

## 4.5  Character and String

Characters, including letters, digits, and symbols are numbered using the ASCII (American Standard Code for Information Interchange) code.
(which have been generalized to extended ASCII code and unicode)
A string, i.e. character string, consists of an ordered sequence of one or more characters.
string.py
```s = "a"           # a string with one character, i.e. length = 1
print(s, ord(s))  # print the character and its ASCII code
i = 97
print(i, chr(i))  # print the ASCII code and the represented character
print(chr(i+1))
```
Program output:
a 97
97 a
b
Explanation
• Double quotes (".. ") enclose a character string, i.e. a sequence of characters.
• The ord() function converts a character to an integer, i.e. the ASCII code.
• The chr() function converts an integer to a character.

# Chapter 5 Operators and Expressions

## 5.1  Assignment operator (=)

To assign a value b to variable a, write
a = b
To assign a value c to variables a and b, write
a = b = c

## 5.2  Arithmetic operators (+, - ,* , / , **, %)

 + addition - subtraction * multiplication / division ** power % modulo, i.e. remainder

## 5.3  Compound assignment( +=, -=, *=, /=, **=, %= )

A compound assignment statement modifies the value of a variable by operating on its value,
e.g. to increase a by 1, write
a += 1
which is equivalent to
a = a + 1
e.g. to replace a by its product with b, write
a *= b
which is equivalent to
a = a * b

## 5.4  Equality and Relational operators ( ==, !=, >, <, >=, <= )

These operators give Boolean values (i.e. true or false):
 == equal to != not equal to (an alternative form is '<>') > greater than < less than >= greater than or equal to <= less than or equal to
e.g.
if a==b:
...

## 5.5  Logical operators ( and, or, not )

Python logical operators for Boolean values are 'and', 'or', 'not'.
e.g. the Boolean expression 0 ≤ x < 3.1416 can be written as
if 0 <= x and x < 3.1416:
...
print( not True )

## 5.6  Precedence of operators

Some operation has higher precedence (i.e. higher priority) and will be executed before others. Operations of the same precedence will be executed from the left to the right, e.g.
a = 1 + 2 * 3
is equivalent to
a = 1 + (2 * 3)
e.g.
a = 5 / 3 / 8
is equivalent to
a = (5 / 3) / 8
The order of precedence of some of the operators, starting from the highest, is
 ** * / % + - <   >   <=   >= ==   !=   not and or
It is a good practice to add parenthesis () to enforce and make explicit the desired order of execution.

# Chapter 6 List and Range

## 6.1  List of numbers

A sequence in mathematics is an ordered set of numbers. For example, consider a sequence {1, 4, 9, 16, 25, 36}
• The sequence has 6 elements
• The elements are numbered from 0 to 5   (not from 1 to 6 ! )
• e.g. element 0 is 1
• e.g. element 4 is 25
 element 0 1 2 3 4 5 value 1 4 9 16 25 36
The above sequence can be stored in a Python data type called list, e.g.
integer_list.py
```X = [1, 4, 9, 16, 25, 36] # create a list of integers
print(X)                  # output whole list
print(X, X)         # output elements 0 and 4
```
Program output:
[1, 4, 9, 16, 25, 36]
1 25
Explanations
• [ ... ] creates a list, which is a variable consisting of 6 integer variables
• The ith element is an individual variable with a variable name X[i]
• Useful in storing data in table forms
• Do not read from or write to a non-existing entry (e.g. X in integer_list.py), or you get an Index Error.

## 6.2  List of variables of mixed types

Elements can be of mixed variable types.
mixed_list.py
```L = [ 1, 3.1416, True, "A", "Hello" ]
print(type(L), type(L), type(L), type(L), type(L), type(L))
```
Program output:
<class 'list'> <class 'int'> <class 'float'> <class 'bool'> <class 'str'> <class 'str'>

## 6.3  Modifying elements in a list

list_modify.py
```X = [1, 4, 9, 16, 25, 36] # create a list of integers
X=5; print(X)          # modify element 1
X.append(49); print(X)    # append a value as last element
X.insert(3,10); print(X)  # insert a value as element 3
del X; print(X)        # delete element 3
X.remove(36); print(X)    # remove the first occurence element by value
```
Program output:
[1, 5, 9, 16, 25, 36]
[1, 5, 9, 16, 25, 36, 49]
[1, 5, 9, 10, 16, 25, 36, 49]
[1, 5, 9, 16, 25, 36, 49]
[1, 5, 9, 16, 25, 49]
Explanations
• A method is a function which operates on an object, e.g. a list. (Functions will be explained later.)
e.g. append(y) is a method for adding an element of value y to the end of the list
insert(i,y) is a method for adding an element as element i
remove(y) is a method for removing the first element in the list with value y
• del X[i] is a statement for deleting element i from the list

## 6.4  Range

We often need simple lists such as [0, 1, 2, 3, ..., N-1]. It is tedious to create the list explicitly if N is large.
A better way is to specify the sequence using a range data type, which can be converted to a list.
range.py
```R = range(5)  # create a range
print( R, type(R) )
X = list(R)   # convert the range to a list
print( X, type(X) )
```
( range.py )
Program output:
range(0, 5) <class 'range'>
[0, 1, 2, 3, 4] <class 'list'>
More general usage of range:
range2.py
```print( list( range(10) ) )     # from 0 to 9
print( list( range(0,10) ) )   # from 0 to 9, i.e. same as range(10)
print( list( range(1,11) ) )   # from 1 to 10
print( list( range(1,11,2) ) ) # from 1 to 10 with a step 2
```
Program output:
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
[1, 3, 5, 7, 9]

# Chapter 7 Program control statements

## 7.1  If, else, elif

The full syntax of if, else, and elif (else-if) statement is:
Syntax
```if <condition> :
statement
elif <condition>:
statement
...
elif <condition>:
statement
else:
statement

```
Each statement can be single line or multiple lines. 'elif' and 'else' statements are optional.
Nested if statement: A statement in an if construction can itself be an if statement, e.g.
Syntax
```if <condition>:
if <condition>:
statement
else:
statement
else:
if <condition>:
statement
elif <condition>:
statement

```
Consider again the quadratic equation
 ax2+bx+c=0
(7.1)
If a < > 0, it has solutions,
x=
 −b ± √ b2 − 4 a c

2a
for D > 0
(7.2)
Else, it has solution,
 x = − c b for b < > 0
(7.3)
quadratic-if3.py
```# solving ax^2 + bx + c = 0 for a=1, b=3, c=-4
from math import *

a=1
b=3
c=-4

if a != 0:
# quadratic equation
D = b*b-4*a*c
if D >= 0:
x1 = (-b + sqrt(D))/(2*a) # 1st root
x2 = (-b - sqrt(D))/(2*a) # 2nd root
print(x1, x2)
else:
# linear equation
if b != 0:
x1 = - c/b
print(x1) # root
```

## 7.2  While loop

See also Sec. 2.7.
A loop iterates (i.e. repeatedly executes) a statement a number of times.
Syntax
```while <condition>:
statement

```
Example: Total mass of balls
There are N=100 balls. The i-th ball (0 ≤ i ≤ N−1) has a mass mi = i kg. Calculate the total mass M of all the balls.
We will calculate
 M = m0 + m1 + m2 + m3 + ... + mN−1 = N−1∑ i=0 mi
where mi = i.
balls_mass_while.py
```# Total mass of N balls
N = 100        # no. of balls
M = 0          # partial sum, which becomes total mass
i=0            # ball counter
while i < N:   # repeat N times
m = i      # m_i (mass of i-th ball)
M += m     # i.e. M=M+m ( add m_i to partial sum )
i += 1     # i.e. i=i+1 ( increase ball counter )
print(M)
```

## 7.3  For loop

We often perform a loop N times, where N is a known constant. This means a counter i runs through each value in the range [0, 1, ... N−1]. We can say:
"For each value of i in the range from 0 to N-1, performs ..."
for.py
```for i in range(5):
print(i, end = " ")
```
( for.py )
Program output:
0 1 2 3 4
Syntax
```for <integer> in <range>:
statement

```
Explanation
• The <integer> variable is a counter, counting the progress of the loop.
• The <range> variable specific the range of values <integer> should take.
• The end option in the print statement specifies what ends the output, instead of a newline character.
The total mass problem can be solved by the following equivalent program:
balls_mass_for.py
```# Total mass of N balls
N = 100             # no. of balls
M = 0               # partial sum, which becomes total mass
for i in range(N):  # repeat N times
m = i           # m_i (mass of i-th ball)
M += m          # i.e. M=M+m ( add m_i to partial sum )
print(M)
```
Alternatively, we can say:
"For each value in the list <list>, performs ..."
for_list.py
```L = [1, 1, 2, 3, 5, 8, 13]  # creates a variable of type 'list'
for i in L:
print(i, end = " ")
```
Program output:
1 1 2 3 5 8 13
Syntax
```for <variable> in <list>:
statement

```

## 7.4  Nested loops

Inside a loop, the content can itself be a loop. This is called a nested loop.
Example: Two dice
List all 36 possible outcomes when rolling two dice.
dice.py
```# Possible outcomes when rolling 2 dice with nested loops
for i in range(1,7):
for j in range(1,7):
print(i, j)
```
( dice.py )
Program output: dice.txt
Example: Cards
List all 52 cards in a deck of cards.
cards.py
```# A deck of cards
for suit in [ 'diamonds', 'clubs', 'hearts', 'spades' ]:
for number in [ 'A', '2', '3', '4', '5', '6', '7', '8', '9', '10', 'J', 'Q', 'K' ]:
print( number, ' of ', suit )
```
( cards.py )
Program output: cards.txt

# Chapter 8 Functions

## 8.1  Function Definition and Usage

Some segments of codes may be repeated a few times in a program, e.g.
Example: Functions
Calculate the surface area and volume of spheres of radii 1, 3, and 7.
SphereProperties.py
```from math import *

r=1
area = 4*pi*r**2
volume = 4/3*pi*r**3
print(r, area, volume)

r=3
area = 4*pi*r**2
volume = 4/3*pi*r**3
print(r, area, volume)

r=7
area = 4*pi*r**2
volume = 4/3*pi*r**3
print(r, area, volume)
```
Program output:
1 12.566370614359172 4.1887902047863905
3 113.09733552923255 113.09733552923254
7 615.7521601035994 1436.7550402417319
Repeated codes can be defined in a function. Applying 'function' in Python involves:
• Defining the function once with the desired codes
• Calling (i.e. using) the function one or more times to execute the codes.
Using function, the above program becomes
SphereProperties-function.py
```from math import *

def Sphere():  # defining a function
area = 4*pi*r**2
volume = 4/3*pi*r**3
print(r, area, volume)

r=1
Sphere() # calling the function

r=3
Sphere() # calling the function

r=7
Sphere() # calling the function
```
Syntax of Function Definition
```def <function name>():
statement

```
Syntax of Calling a Function
```<function name>()

```
Explanation
• The statement inside the function definition is the function's body.
• A function must be defined before it can be called.
• When a function is called by writing <function name>() , it is as if the statement <function name>() is replaced by the function's body. (See function-inserted.py .)
Advantages of functions
• Important way to repeat identical or similar code segments
• Function name tells the purpose of a code segment and enhance readability (i.e. may also be helpful to define non-repeating codes as function)
• Breaking a large block into smaller blocks (usually within a page long) to enhance readability.

## 8.2  Arguments of functions

In the example above, the radius is passed (i.e. supplied) to the function using r as a global variable (i.e. a variable accessible everywhere in the program). A much better approach is passing r as a function argument (i.e. function parameter), e.g.
SphereProperties-function.py
```from math import *

def Sphere(r):  # defining a function
area = 4*pi*r**2
volume = 4/3*pi*r**3
print(r, area, volume)

Sphere(1)  # r=1
Sphere(3)  # r=3
Sphere(7)  # r=7

```
Syntax : Function Definition with Arguments
```def <function name>( [<variable name>] [, ...] ):
statement

```
( The square brackets [...] mean optional parts. )
A function can have multiple arguments.
Example: Function Definition with multiple arguments
Calculate the surface area and volume of spheres of radii 1, 3, and 7 and densities 7.87, 8.96, 11.36 respectively.
function-argument2.py
```from math import *

def Sphere(r, rho):  # defining a function
area = 4*pi*r**2
volume = 4/3*pi*r**3
mass = rho * volume
print(r, area, volume, mass)

Sphere(1, 7.87)  # r=1, rho=7.87
Sphere(3, 8.96)
Sphere(7, 11.36)

```

## 8.3  Returned value of function

A mathematical function can be defined as a Python function, e.g.
Example: The Square Function
Calculate 1.52 by defining a function called sqr.
sqr.py
```def sqr(x):
y = x**2
print(y)

sqr(1.5)
```
( sqr.py )
All the functions above send results to the screen. A drawback is that results cannot be used for further calculation.
Example: The Square Function, again
Calculate 1.52 sin(π/6) by defining a function called sqr.
Solution is to define a function which returns a value:
sqr_return.py
```from math import *

def sqr(x):
y = x**2
return y  # return a value to the calling line

sum = sqr(1.5) * sin(pi/6)  # the line which calls the function sqr
print(sum)
```
Syntax : Function Definition with Returned Value
```def <function name>( [<variable name>] [, ...] ):
statement
return <value>
}

```
Explanation
• The "return <variable name>" statement specifies which value is the function's returned value. It also ends the execution of the function, and program continues again from after the calling line.
• <function name>() at the calling line is substituted by the returned value.
Example: Returned values of Functions
Calculate the total mass of spheres of radii 1, 3, and 7 and densities 7.87, 8.96, 11.36 respectively.
function_return.py
```from math import *

def Sphere(r, rho):  # defining a function
volume = 4/3*pi*r**3
mass = rho * volume
return mass

m1 = Sphere(1, 7.87)
m2 = Sphere(3, 8.96)
m3 = Sphere(7, 11.36)
print (m1+m2+m3)
```

## 8.4  Returning multiple values

A function can return more than one values.
Example: Returned values of Functions
Calculate the total mass and total volume of spheres of radii 1, 3, and 7 and densities 7.87, 8.96, 11.36 respectively.
function_return_multi.py
```from math import *

def Sphere(r, rho):  # defining a function
volume = 4/3*pi*r**3
mass = rho * volume
return volume, mass  # returning a list of 2 values

L = Sphere(1, 7.87)  # assign list to variable L
v1 = L            # extract values from list
m1 = L

v2, m2 = Sphere(3, 8.96)  # assign list's values directly to variables
v3, m3 = Sphere(7, 11.36)

print(v1+v2+v3, m1+m2+m3)
```
Explanation
• "return x, y" allows a function to return a tuple, which is a constant list.
• "x, y = L" assigns values in the list to variables x & y.

## 8.5  Mathematical Functions

Many useful mathematical functions are pre-defined in the math library (requires "from math import *"), including
 Function Description sqrt(x) square root exp(x) exponentiation log(x) natural logarithm log10(x) base-10 logarithm fabs(x) absolute value floor(x) truncate to whole number (not rounding) sin(x) sine cos(x) cosine tan(x) tangent asin(x) arc-sine acos(x) arc-cosine atan(x) arc-tangent
(trigonometric functions assume parameters in radian)

# Chapter 9 Jupyter Notebook and Google Colab Notebook interface is a worksheet-like environment for both (1) word processing and (2) program development and execution. Jupyter Notebook is a popular notebook environment originally for Python and now includes many other programming languages. Its new version is called JupyterLab. Google Colaboratory, i.e. Google Colab, is an online Jupyter notebook environment. Files are stored in Google Drive. With Google Colab, we can describe and solve our problem about spheres' masses. The resulting notebook can look like a simple report. This Colab notebook is accessible at https://colab.research.google.com/drive/1E7nws_7QaMpgQN7FZWzvW0dhzCUkW499.
Explanation
• Press "+ Text" to create a text cell for entering text as in a word-processor.
• Press "+ Code" to create a code cell for entering program codes.
• We can run an individual code cell, or "run all" the code cells.
• Variables from one cell is available to subsequently executed cells.
• Result of the last line of code in the n-th code cell is displayed and assigned to the variable Out[n].
• A notebook can be make available to others in read-only or editable form.

# Chapter 10 Strings and Input / Output

## 10.1  Escape sequence

An escape sequence is a combination characters that has a special meaning, e.g.
 \n Linefeed character, i.e. to start a new line \t tab character, i.e. jump to next tab position (e.g. column 1,9,17,25,...) \′ single quote \" double quote
e.g.
escape_sequence.py
```print( "A quote (\' or \") can be included in a string" )
print( "1\t10\t100\n1000\t10000\t100000") # output a simple table of numbers
```
Program output:
A quote (' or ") can be included in a string
1       10      100
1000    10000   100000

## 10.2  String operations

Strings can be joined or shortened, e.g.
string_operations.py
```s1 = "joining" + " strings"  # add two strings
s2 = s1[8:14]  # substring of characters 8 to 14
s3 = s1[8:]    # substring of characters 8 to end of string
s4 = s1[0:-4]  # substring of characters 0 to 4th last character.
print(s1 + '\n' + s2 + '\n' + s3 + '\n' + s4)
```
Program output:
joining strings
string
strings
joining str
These operations for strings are generally applicable to lists, since a string is a list of characters.

## 10.3  Formatted strings

( Requires Python 3.6 or newer, e.g. Google Colab or CodingGround, but NOT OnlineGDB. )
Formatted strings provide detailed controls on the construction of strings. e.g.
formatted_strings.py
```x = 1
y = 3
print( f"{x} / {y} = {x/y}")  # an expression inside { } will be evaluated
print( f"{x:10d}{y:10d}") # controlling width
print( f"{x/y:10.3g}{x/y:10.3g} {x/y*1e10:.3g}")  # controlling width and no. of s.f.
```
Program output:
1 / 3 = 0.3333333333333333
1         3
0.333     0.333 3.33e+09
Explanation
f" ... "
constructs a formatted string
{ ... }
encloses an expression to be evaluated
<integer value>:<width>d
formats an integer to a width <width> right-justified
<float value>:<width>.<n>g
formats a float to a width <width> with <n> significant figures right-justified. Scientific notation is used when appropriate.

## 10.4  Input

The input() function reads user's input from the keyboard, e.g
input.py
```S = input("Please enter your message: ")
print( S, type(S) )
```
( input.py )
Program output (if user enters 'Hello'):
Please enter your message: Hello
Hello <class 'str'>
Program output (if user enters '12'):
Please enter your message: 12
12 <class 'str'>
Program output (if user enters '12 25'):
Please enter your message: 12 25
12 25 <class 'str'>
Explanation
• The optional string in "( ... )" is used as a prompt to give user instructions.
• Program waits for user input until user press "enter".
• input() returns a single string containing user input.
• The string may contain one or more numbers in a string format (i.e. ASCII format with spaces inside).
To extract numerical values from user input:
input2.py
```S = input("Enter two numbers: ")
s1, s2 = S.split()       # splitting string into words
print( s1, s2, s1+s2 )   # adding (i.e. joining) strings, rather than adding numbers
x=float(s1); y=float(s2) # converting string to float
print( x, y, x+y )       # adding numbers
```
Program output (if user enters '13 28'):
Enter two numbers: 13 28
13 28 1328
13.0 28.0 41.0
Explanation
• .split() is a method (i.e. a function defined for a data type) of strings. Words in a string separated by spaces will be broken down into individual strings.

## 10.5  File Output

Very often, one wants to output result to a file rather than to the screen, e.g.
fileout.py
```ofile = open("numbers.txt", "w")
for i in range(10):
ofile.write( str(i) + " ")
ofile.close()
```
It creates a file called numbers.txt.
• For OnlineGDB, the file is shown in a new tab and can be downloaded by pressing a "download code" icon, the rightmost icon on the top icon bar.
• For Google Colab, the file can be downloaded by first pressing a "files" icon on the left icon bar.
• For Python installed in MS Windows or Linux, the file is in the "current directory" in the file system of the computer.
Explanation
open( <file name>, "w" )
Create and open a file with name <file name> for writing. It returns a file object, i.e. a variable representing the file.
.write( <string> )
A method of the file object which outputs the string to the file.
.close()
A method of the file object which closes the file and finishes outputting.
.txt
A filename extension usually denoting text file format and can be opened by e.g. microsoft notepad.
Example: File Output
Output to a file a table of values from the normal distribution function defined by
f(x) = 1

 √ 2π
e−x2/2
(10.1)
for x=−5, −0.49, −0.48, ... 5.
normal_dist.py
```from math import *

def f(x):
return (1/sqrt(2*pi)) * exp(-x**2/2)

ofile = open("normal.txt", "w")
x = -5
while x <= 5:
ofile.write( str(x) + " " + str(f(x)) + "\n" )
x += 0.01
ofile.close()
```
The created file is normal.txt.
Explanation
• The str( ) function converts a value to the string data type.
The data file can be used to plot a graph using e.g. MS Excel:

## 10.6  File Input

Example: file input
Read the file normal.txt and sum up all values in the second column.
file_input.py
```infile = open("normal.txt", "r")
sum=0
for line in infile:
s1, s2 = line.split()
x=float(s1); y=float(s2)
sum += y
print(sum)
infile.close()
```
Explanation
open( <file name>, "r" )
Open a file with name <file name> for reading. It returns a file object.
for <string variable> in <file object>:
The file object supplies a list of lines read from the file. The for-loop loops over each line in the list.

# Chapter 11 Python Libraries

## 11.1  Introduction

Python has built-in data types and functions for essential operations. More data types and functions can be added by using libraries (also called modules) to extend Python's capabilities. Some popular libraries are pre-installed with Python. Some others require downloading and installation separately. For example, OnlineGDB has about 500 libraries installed. Important libraries include math, numpy, matplotlib, scipy, cmath, etc. To see a full list of installed libraries, type ' help "modules" '.
Advantages of Python's capability to use libraries (rather than bulid-in everything):
• Libraries can be developed independently by different people, rather than by the original Python developers. This greatly speeds up development.
• Users have more choices over libraries. Some libraries may have similar functions and compete with each others. Users can choose their favorite ones.
• Functions with identical names in different libraries are acceptable, i.e. easier to name functions.
Before using a library, include the import command.
• To import an entire library and make all functions directly usable as if built-in:
from math import *
print( sin(pi) )
• To import only part of a library:
from math import sin, pi
print( sin(pi) )
• To import an entire library under the library's name:
import math
print( math.sin(math.pi) )
• To import an entire library under a new (usually shortened) name:
import math as m
print( m.sin(m.pi) )

## 11.2  NumPy

NumPy is a Python library for numerical calculations. Its functionalities include:
• Arrays in one or more dimensions
• Linear algebra
• Fourier transform
• random numbers
Array
An array is a list with all elements of the same type, e.g. integer or float. (Many programming languages support arrays, but not lists.)
array.py
```import numpy as np
L = [1, 4, 9, 16, 25, 36]   # create a list of integers
X1 = np.array(L); print(X1) # convert to array
X2 = np.append( X1, [49, 64]); print(X2)  # append elements to array
X3 = X2[1:7]; print(X3)  # extract sub-array of elements 1 to 7
X4 = X3[:-2]; print(X4)  # extract sub-array from elements 0 excluding last 2
```
( array.py )
Program output:
[ 1 4 9 16 25 36]
[ 1 4 9 16 25 36 49 64]
[ 4 9 16 25 36 49]
[ 4 9 16 25]
i.e. array admits indexing operators similar to those for lists (see Sec. 6.3).
array2.py
```import numpy as np
X = np.arange(4);         # creates an array, analogous to range
print(X, X+1, 2*X, X**2)  # simple algebric operations of array elements
print(np.exp(X))          # mathematic function for array elements
print(np.sum(X))          # sum up all elements
Y =np.linspace(2,8,4);    # creates an array with 4 equally spaced points
print(Y, X+Y, X*Y)        # simple algebric oerpations of array elements
```
Program output:
[0 1 2 3] [1 2 3 4] [0 2 4 6] [0 1 4 9]
[ 1. 2.71828183 7.3890561 20.08553692]
6
[ 2. 4. 6. 8.] [ 2. 5. 8. 11.] [ 0. 4. 12. 24.]
Explanation
X+1, 2*X, X**2, X+Y, X*Y
Algebraic operations on arrays are performed element by element. In many other languages, a for loop over each element is needed.
arange( [<start>, ] <stop> [, <step>] )
creates an array with evenly spaced values from <start> to <stop> (but excluding <stop>) with a step size of <step>. It is similar to range(), but <step> need not be an integer.
linspace( <start>, <stop>, <number> )
creates an array with evenly spaced values from <start> to <stop> (and including <stop>) with <number> elements.
Two dimensional Arrays
A two-dimensional array can store a table of numbers for further processing, e.g.
array2d.py
```import numpy as np
X = np.array( [[1, 2, 3],
[4, 5, 6]]) # convert a list of list to a 2D array
print(X)        # output entire array
print(X[0,1])   # output element at row 0, column 1
```
Program output:
[[1 2 3]
[4 5 6]]
2

## 11.3  Matplotlib

Matplotlib is a graph plotting library usable in Google Colab.
For example, to evaluated and plot the normal distribution function in Eq. 10.1, we can use the following program:
normal_dist_plot.py
```# calculate and plot normal distribution (run in google colab)
from math import *
import matplotlib.pyplot as plt
import numpy as np

X = np.linspace(-5,5,101)            # create array of values from -5 to 5 with 101 elements
Y = 1/sqrt(2*pi) * np.exp( -X**2/2 ) # calculate P(x) for each element in X

plt.plot(X, Y)                       # plot a graph
plt.xlabel('x')
plt.ylabel('P(x)')
plt.title('Normal distribution')
plt.savefig('Normal_distribution.jpg')
```
Click https://colab.research.google.com/drive/1JmPTJX8tuvv9TtczHwuV6fFYyW0DFkdR to open this Colab notebook. The generated file (Normal_distribution.jpg) containing the graph can be downloaded and is shown below:

# Chapter 12 Advanced topic: Classes

A new data type can be created by defining a new class. For example, the following program defines a complex number class (which in fact is already available in the library cmath) and adds two complex numbers:
complex_class.py
```class Complex:                 # define a complex data type
def __init__(self, x, y):  # initialization function of complex variable
self.re = x            # creates variable re within the complex variable
self.im = y            # creates variable im within the complex variable

z1 = Complex(1, 1)       # creates a complex variable
z2 = Complex(1, 2)       # creates another complex variable
z2.im = 5                # variables within complex variable can be modified
zsum = Complex( z1.re + z2.re, z1.im + z2.im )  # addition of complex two variables
print(zsum.re, zsum.im)  # output complex variable by outputing components
```
Program output:
2 6
Explanation
<class name>( ... ) ,     e.g. Complex(1, 1)
Create a variable, i.e. an object, of this class.
class <class name>: ,     e.g. class Complex:
Start the definition of a class.
__init__(self [, ...] )
The constructor function of the class. When an object of this class is created, it is automatically called by the Python interpretor. The first argument (usually represented by the variable named "self") is the created object itself.
self.<attribute name> = <value> , e.g. self.re = x
This assignment operation creates a variable inside the object. Such a variable is called an attribute of the object.
<object name>.<attribute name> , e.g. self.re, z1.re
An attribute of an object can be assessed inside or outside the class definition.
The addition and output of complex numbers can be improved as follows:
complex_class2.py
```class Complex:                 # define a complex data type
def __init__(self, x, y):  # initialization function of complex variable
self.re = x            # creates variable re within the complex variable
self.im = y            # creates variable im within the complex variable

def add(self, z):          # a method for addition
return Complex(self.re + z.re, self.im + z.im)

def __add__(self, z):      # an operator for addition
return Complex(self.re + z.re, self.im + z.im)

def __str__(self):         # convert the number to a string, used by print()
return str(self.re) + '+' + str(self.im) + 'i'

z1 = Complex(1, 1)
z2 = Complex(1, 3)
print( z1, z2, z1.add(z2) )  # addition using a method
print( z1, z2, z1 + z2 )     # addition using an operator
```
Program output:
1+1i 1+3i 2+4i
1+1i 1+3i 2+4i
Explanation
def add(self, z):
A function defined inside a class definition is called a method.
z1.add(z2)
Calling the method "add" of the object z1 with an argument z2.
def __add__(self, z):
Define a special method of the class associated with the "+" operator.
def __str__(self)
Define a special method of the class called by str() and print() functions.
- End of Lecture Notes -

File translated from TEX by TTH, version 4.15.
On 8 Apr 2021, 15:05.