The Shape of Data¶
When we now take a look at our output we notice something curious:
Our calculation yielded us a fractional amount of groups.
While it is correct that
118 / 7 = 16.857…, what we actually wanted to do is a calculation based on whole numbers, ignoring the fractions.
To understand what is happening, we need three fundamental points of knowledge.
1. Data Types¶
Beside its name and value all variables also have a data type associated with them. From the computers’ perspective, all information is just a sequence of 1’s and 0’s in memory. The data type determines what kind of information is stored at a given spot in memory and which operations are allowed to do with with these values.
Assume the computer sees the 32-bit sequence
01000100011000010111010001100001 in its memory as the value for a given variable.
Depending on what we assign as a data type, the interpretations can differ widely:
- As text, this would represent the word
"Data"(without the quotes)
- As a fractional number, this would be
- As a whole number it would mean
The data type of a variable is determined during the assignment of a value. There are many different data types and we will get to know a few of them better as we go along.
2. Type Casting¶
Sometimes, the current data type of a variable does not match the operation we want to do with it. There is a concept called type casting which allows to convert between various data types while retaining the meaning of the stored value.
You cold convert between the whole number
2, the fractional number
2.0 or the text representation
3. Implicit Casting¶
There are situations in which type casting occurs implicitly. While this is usually very convenient, it may also result in surprises if you are not aware that this may happen in a particular case.
Understanding our Type Problem¶
Note: The code in this section should best be done using the REPL. It is very well suited for such investigative experiments and you do not want to have the “just trying stuff out” as part of your productive code that you will share with others.
Let’s start by checking the data types of the values that go into the division.
We will use the built-in
type(…)-function, which will give us the data type of a value or variable.
<class 'int'> seems a bit cryptic.
We can ignore the
class-part for the time being, for us it is sufficient to know that class are basically data types.
More interesting is the
int-section, since it lets us know that we are dealing with an integer here.
Integers are whole numbers with no decimal fraction, like …
Many data types have abbreviations associated with them. You can look up the common ones in the data types overview.
Look up the data types for
INDIVIDUALS_PER_GROUP and for
Try an educated guess what may have happened here.
We are dealing with an implicit type casting here.
While both operands are integers, the result of any division is silently cast to a so-called
This is short for floating point numbers which represent nubers with decimal fractions, such as
Usually this makes a lot of sense, but here, we have something different in mind…
That’s my Type¶
We have two options to remedy our problem.
1. Cast to Integer¶
Since we want a whole number (
int) instead of a fractional number (
float), we can use the previously mentioned type casting for this purpose.
This is done by using a built-in function with the same name as the target type and pass in the original value.
2. Use a Different Operator¶
Alternatively, Python also offers a division operator
// for a pure integer division (without remainder).
Both approaches are equally valid.
- Variables have a data type
- The data type determines which kind of information the variable carries
- It also determines which operations are possible with these values
- You can convert values between different data types
This is the code that we have so far: