Session 5: Numbers#
Introduction#
You may be wondering how you have managed to learn quite a lot of Python so far, without really doing anything with numbers - well, that starts here.
Task 1#
In a terminal window, navigate to your
PHAR2062/Session 5 - Numbers
folder.Using your text editor, create a file in this folder called “numbers.txt”, with the content:
1.25 3.75 4.56 7 14
make sure there is an extra space character at the end of the last line (i.e., “14 “)
Start a Jupyter Notebook session, and create a fresh, empty, notebook.
Using the Python code you wrote in the last session as a guide, write a script that will read the contents of this file into a
list
called “numbers” (remembering to strip off those pesky\n
characters at the end of each line), and then print it.
Analysis#
Based on what you have learned so far, you shouldn’t have found this task too hard, but if you get really stuck:
Here’s a suggested solution.
numbers_file = open('numbers.txt')
numbers = []
for line in numbers_file:
numbers.append(line[:-1])
numbers_file.close()
print(numbers)
Task 2#
Copy the following code into a fresh cell at the bottom of your notebook, then run it:
print(numbers[0] + numbers[1])
Analysis#
You probably made a guess at what this piece of code would do - and you were probably surprised that it did something different!
If you thought that the code would print the result of adding the second of the items in the list numbers
to the first item in that list, you are right - that is exacly what the code has done.
But: what are numbers[0]
and numbers[1]
? They are strings - sequences of characters - they are not numerical quantities. “Adding” together two strings (in Python) means returning the result of appending the characters of the second string to the first one - which you will see, is what has happened.
In order to get Python to do what we really are wanting, we need to convert the data items from strings into a different type that Python recognises as being “number-like”.
Python understands two different basic numerical types: floating-point numbers (like 1.25, 4.56, in Python often called “floats”) and integers (like 10, 14, in Python often called “ints”).
Task 3#
Copy the following code into a fresh cell at the bottom of your notebook, then run it:
float_a = float(numbers[0])
float_b = float(numbers[1])
float_c = float(numbers[2])
int_d = int(numbers[3])
int_e = int(numbers[4])
print(type(numbers[0]))
print(type(float_a))
print(type(int_d))
print(float_a, float_b)
print(int_d, int_e)
str_a = str(float_a)
str_d = str(int_d)
print(str_a, str_d)
print(type(str_a), type(str_d))
float_sum = float_a + float_b
int_sum = int_d + int_e
print(float_a, "+", float_b, "=", float_sum)
print(int_d, "+", int_e, "=", int_sum)
Analysis#
The first four lines introduce two new Python functions: float()
and int()
. You can see them being used in assignment statements to create new variables, float_a
, float_b
, float_c
, int_d
, and int_e
, from *arguments that are strings.
Lines 6-8 introduce another new Python function: type()
. You can probably work out that this takes some object as its argument, and returns the type of that object. So you see that float_a
is a float, and int_d
is an int.
Lines 10 and 11 show that if you just print()
a float or an int, it “looks” just like the corresponding string object it was created from.
Lines 13-16 introduce one further Python function: str()
. As you can work out, here it is doing the “reverse” data type transformation - creating strings out of floats or ints.
Lines 18 to 21 show (from what gets printed out) how using these new numerical data types, Python maths works like you are expecting it to!
Note
Converting an item of one data type into an item of a different data type is called casting.
Fairly obviously, some sorts of casting are possible, others are are not or make no sense (e.g. float("hello")
).
Task 4#
Let’s look at other types of mathematical operations. Copy the following code into a fresh cell at the bottom of your notebook, then run it:
print(float_a - float_b)
print(float_a * float_b)
print(float_b / float_a)
print(int_e - int_d)
print(int_d * int_e)
print(int_e / int_d)
Analysis#
The results should be as you expected: in Python you subtract one number from another using -
, multiply two numbers using *
, and divide one by another using /
. A bit of extra detail though:
Notice from line 3 that if you divide one
float
by anotherfloat
, the answer is afloat
(here “3.0”), even if the value, in essence, is an integer.Notice from lines 4 and 5 that if you add, subtract, or multiply two
int
s, you get anint
.Notice however from line 6 that if you divide one
int
by anotherint
, you get afloat
, even if the value is technically integral.
Now some terminology and detail:
The
+
,-
,*
and/
symbols are known as operators. Operators act on operands - the ‘things’ to the left and right of them. They take the values of each of them and combine them in some way to give a result - something that has a type, and a value. That value may be assigned to a variable (e.g.float_sum = float_a + float_b
) or the result may be used directly (e.g.print(float_a - float_b)
) without creating an intermediate named variable to hold it.Actually, not all operators have to act on something both to the left AND right of them - the
-
operator, for example, still “works” if there is only something to its right (e.g.negative = - float_a
would be valid Python). Operators that work on two things are called binary operators, ones that work on just one are called unary operators. Both-
and+
can be used as either unary operators or binary operators (though there is not much point in using+
in that way!), but*
and/
can - pretty obviously - only be used as binary operators.
Note
Notice the similarity in the language we have used to describe what operators are and how they are used, and the language we have used previously to describe how functions work. This is deliberate, because operators can be regarded as a convenient and familiar way to write something that could have been done by a function - if it existed. So for example:
c = a + b
could perhaps have been:
c = add(a, b)
Well, infact that’s exactly what operators are - “disguised” functions. It’s nothing to be concerned about at this stage, but you may come across it later if you dive much deeper into Python.
Task 5#
Copy the following code into a fresh cell at the bottom of your notebook, then run it:
print(float_b + float_c)
Analysis#
Most likely, the result is not what you expected - it seems Python cannot reliably even add simple numbers together! To understand what’s going on, we need to dig a bit deeper into how Python actually stores data about floating point numbers in the computer’s memory.
As I’m sure you are aware, computers store numbers in binary. For integers this is easy to appreciate, for example decimal number 4 is stored as ‘100’ (1*4 + 0*2 + 0*1), and decimal number 5 as ‘101’ (1*4 + 0*2 + 1*1), etc.
What about floating point numbers? The same concept is just extended - for example 4.5 would be stored as ‘101.1’ ( 1*4 + 0*2 + 0*1 + 1*1/2).
The trouble with this however, is that fractions that are simple to express in decimal (‘base 10’) are not neccessarily easy to represent in binary as a sum of a 0 or 1 halves, plus 0 or 1 quarters, plus 0 or 1 eighths, etc. As it happens, 4.56 is such a number (it’s ‘100.1000111101011101100110011001100110011001100110010111101110100111’ approximately!). Python only allows floats to use up to 64 bits of storage, so there is always the possibility of ‘rounding errors’ when maths is done with floating point numbers. In most cases the result of this rounding is a tiny error, too small to be significant in a practical calculation, but sometimes it can be “cosmetically” surprising - as here.
Task 6#
Copy the following code into a fresh cell at the bottom of your notebook, then run it:
a = 1
b = 1.0
c = -3.5
print(type(a))
print(type(b))
print(type(c))
Analysis#
OK - so just as before you learned how to create string variables from string literals (e.g. greeting = "hello"
), here you see how to create floating point variables and integer variables from float and int literals. The rule is that if the literal has no decimal point in it, it’s assumed to be an int, whereas if it does contain a decimal point it’s assumed to be a float.
Programming Challenge
In a fresh cell at the bottom of your notebook, write Python code to calculate and print the sum of all the numbers in the file numbers.txt
. Try to write it in a way that will work no matter now many numbers are in the file (as long as there is only one number per line, and there is a space character after the number in the last line. Note: For this challenge you can assume all the numbers in the files are float
s!).
Hint
You can update the value of a variable with code like: sum = sum + value
- could this be useful within an iteration loop?
Once you have this working in a notebook, convert it into a standalone Python program called analyze.py
that you can run from the command line in a terminal window - look back at the material from the first two sessions for a refesher, if needed.
Summary#
In this session you have:
been introduced to Python’s two basic numerical data types: floats and ints.
seen how they can be created from literals or by converstion of strings.
learned about Python’s
type()
function that can tell you if a variable is a string, int, or floatlearned what the
str()
,int()
, andfloat()
functions do.seen how you can do simple maths with them, and been introduced to a few subtleties, like the issue of rounding errors.
Further study#
Now that you have been introduced to strings, numbers, and lists, it’s a good time to start looking at some of the valuable on-line resources for learning and using Python effectively. One of these is the Official Python Documentation, which includes a pretty comprehensive tutorial.
For now, consider browsing up to and including section 3.1 Using Python as a Calculator