The Primitive Types, and Where They Stop
Chapter Four
Syllabus topic Module 1, "Abstract Data Type: Different Data Types"
Pages 11 to 13 of 411
In one line
The primitive types are the ones the language gives you ready made, each holding a single value, and the moment a problem has many values they are not enough on their own.
The four families
Every language you will meet has these, whatever it calls them.
| Family | Holds | Python | C |
|---|---|---|---|
| Integer | whole numbers | int | int, long, short |
| Real | numbers with a fractional part | float | float, double |
| Character | one letter or symbol | (a str of length 1) | char |
| Boolean | true or false | bool | _Bool |
Python has no separate character type: a single letter is just a string of length one. C has no separate boolean until C99, and used integers instead, 0 for false. These differences are examinable, so the table above says both.
What a primitive can and cannot do
n = 42
r = 3.75
c = "Z"
flag = False
print("integer :", n, type(n).__name__, "| n * 2 =", n * 2)
print("real :", r, type(r).__name__, "| r * 2 =", r * 2)
print("character:", c, type(c).__name__, "| ord(c) =", ord(c))
print("boolean :", flag, type(flag).__name__, "| not flag =", not flag)
print()
print("integer division 7 // 2 :", 7 // 2)
print("real division 7 / 2 :", 7 / 2)
print("0.1 + 0.2 == 0.3 :", 0.1 + 0.2 == 0.3)
print("0.1 + 0.2 is actually :", 0.1 + 0.2)integer : 42 int | n * 2 = 84
real : 3.75 float | r * 2 = 7.5
character: Z str | ord(c) = 90
boolean : False bool | not flag = True
integer division 7 // 2 : 3
real division 7 / 2 : 3.5
0.1 + 0.2 == 0.3 : False
0.1 + 0.2 is actually : 0.300000000000000040.1 + 0.2 is not 0.3, and that is not a bug. A real number is stored in a fixed number of bits, and most decimal fractions cannot be written exactly in binary any more than one third can be written exactly in decimal. So a float is an approximation, and two floats should almost never be compared with ==. Compare the difference against a small tolerance instead. This costs students marks and costs programmers money, and it is a property of the type, which is why it belongs here.
Where the limits are
Integers in most languages have a largest value. Python's do not, and it is worth seeing the difference rather than being told it:
import sys
print("Python int: no fixed maximum. 2 ** 200 =")
print(2 ** 200)
print()
print("float: largest and smallest, from the machine itself")
print(" max float :", sys.float_info.max)
print(" min normal:", sys.float_info.min)
print(" digits it can be trusted to:", sys.float_info.dig)
print()
print("what happens past the top of a float:")
big = sys.float_info.max
print(" max * 2 =", big * 2)The Primitive Types, and Where They Stop
Python int: no fixed maximum. 2 ** 200 =
1606938044258990275541962092341162602522202993782792835301376
float: largest and smallest, from the machine itself
max float : 1.7976931348623157e+308
min normal: 2.2250738585072014e-308
digits it can be trusted to: 15
what happens past the top of a float:
max * 2 = infA float that grows past its largest value becomes inf rather than wrapping. A C integer that grows past its largest value wraps to a negative number silently, which is the more dangerous behaviour and the reason overflow is a standard examination topic.
Where the primitives stop, and the paper begins
Here is the wall, and the whole of the rest of this book is the answer to it.
A primitive holds one value. Consider the smallest realistic problem: the marks of the students in a class.
mark1 = 78
mark2 = 65
mark3 = 91
print("average of three:", (mark1 + mark2 + mark3) / 3)
print()
print("now do it for sixty students, with sixty named variables.")
print("and then sort them.")
print("and then find the student ranked seventh.")average of three: 78.0
now do it for sixty students, with sixty named variables.
and then sort them.
and then find the student ranked seventh.Three problems appear at once, and none of them is about arithmetic.
You cannot write sixty variables and mean it. The program would have to be rewritten for a class of sixty one.
You cannot loop over separately named variables. A loop needs a way to say "the next one", and separate names have no next.
You cannot sort them. Sorting means moving values around by position, and a name is not a position.
What is needed is a way to hold many values under one name, reachable by position. That is the array, it is the next structure in this book, and every other structure here is a response to something the array cannot do.
Quick revision
- The primitive types are integer, real, character and boolean; each holds a single value.
- Python has no separate character type (a one-letter string) and its booleans are a kind of integer.
//is integer division,/is real division.- Floats are approximations:
0.1 + 0.2is not exactly0.3, so never compare floats with==;
compare the difference against a tolerance.
- Floats have a largest value and overflow to
inf. Fixed width integers in C wrap silently instead. - Python integers have no fixed maximum.
- A primitive holds one value. A problem with many values needs many values under one name, reachable
by position, and that is where data structures begin.
The Primitive Types, and Where They Stop
Test yourself
1. Name the four primitive families and what each holds. Integer (whole numbers), real or float (numbers with a fractional part), character (one symbol), boolean (true or false).
2. Why should two floats not be compared with ==? Because a float is a binary approximation of a decimal value, so arithmetic leaves tiny errors: 0.1 + 0.2 gives 0.30000000000000004. Compare the absolute difference against a small tolerance.
3. What is the result of 7 // 2 and how does it differ from 7 / 2? 7 // 2 is 3, integer division discarding the fraction. 7 / 2 is 3.5.
4. What happens when a float exceeds its maximum, and how does a fixed width C integer differ? The float becomes inf. The C integer wraps around to a negative value with no warning, which is the more dangerous of the two.
5. Give three reasons sixty separately named variables cannot hold a class's marks. The program cannot be written for an unknown class size; a loop has no way to move to the next one; and sorting needs positions, which names do not have.
6. What property must the next structure have, that a primitive does not? It must hold many values under one name and let any of them be reached by position.
The rest of this subject
These notes are cut from the University's printed syllabus. Open the syllabus itself, or the past papers, for the same subject.