The idea
Most of what a data analyst calculates is arithmetic: totals, averages, percentages, growth rates, tax. Python is an excellent calculator, as long as you know its rules: which type you get back, how division works, why 0.1 + 0.2 isn't exactly 0.3, and how to turn the text you read from files and forms into numbers you can calculate with.
ints and floats
Python has two main number types:
intfor whole numbers:3,-12,95000floatfor numbers with a decimal point:4.7,0.11,3.0
When you mix them, the result is a float, because a float can hold everything an int can:
print(3 + 2)
print(3 + 2.0)
print(type(3 * 1.5))
5
5.0
<class 'float'>
Long numbers are easier to read with underscores, which Python ignores: revenue = 12_500_000 is the same as 12500000.
The arithmetic operators
| Operator | Meaning | Example | Result |
|---|---|---|---|
+ | add | 7 + 2 | 9 |
- | subtract | 7 - 2 | 5 |
* | multiply | 7 * 2 | 14 |
/ | divide | 7 / 2 | 3.5 |
// | floor divide | 7 // 2 | 3 |
% | remainder (modulo) | 7 % 2 | 1 |
** | power | 7 ** 2 | 49 |
Python follows the usual order of operations: brackets, then powers, then *, /, //, %, then + and -. When in doubt, add brackets. They cost nothing and make your intent obvious:
price = 100000
discount = 0.1
print(price - price * discount)
print((price - 20000) * 2)
90000.0
160000
Three kinds of division
This is where Python surprises people coming from Excel.
/ always gives a float, even when the answer is a whole number:
print(10 / 2)
5.0
// (floor division) gives the whole-number part, rounding down, and % (modulo) gives what's left over. They're a team, perfect for splitting quantities into groups:
minutes = 135
hours = minutes // 60
leftover = minutes % 60
print(f"{hours} h {leftover} min")
eggs = 26
print(f"{eggs // 12} full boxes, {eggs % 12} loose")
2 h 15 min
2 full boxes, 2 loose
% has another everyday use: number % 2 == 0 is True for even numbers, because even numbers have no remainder when divided by 2.
Floats aren't perfectly precise
Computers store floats in binary, and many decimals can't be stored exactly. Most of the time you won't notice, but sometimes you will:
print(0.1 + 0.2)
print(round(0.1 + 0.2, 2))
0.30000000000000004
0.3
This isn't a Python bug; every language does it. The practical rules:
- Use
round(value, digits)when displaying or storing a final result. - Don't compare floats with
==directly. Compare the rounded values, or check that the difference is tiny. - Money is usually safest as an
intof the smallest unit (whole Rupiah here), or with Python'sdecimalmodule for accounting work.
Note that round() with no second argument returns an int: round(4.6) is 5. Python rounds exact halves to the nearest even number, so round(2.5) is 2, which avoids skewing totals when you round many values.
Other handy built-ins
A few calculations come up so often that Python has them built in, ready to use without importing anything. You'll use these all the time for things like "how big was the change, ignoring whether it went up or down?" or "which is cheaper, this supplier or that one?":
print(abs(-3500)) # distance from zero
print(min(95000, 65000)) # smallest
print(max(4, 9, 2)) # largest
print(pow(2, 10)) # same as 2 ** 10
3500
65000
9
1024
For more maths, import the math module:
import math
print(math.ceil(4.1)) # round UP to a whole number
print(math.floor(4.9)) # round DOWN
print(math.sqrt(144))
5
4
12.0
Updating a variable: += and friends
Programs constantly update a value based on what it already is. Five items are sold, so stock goes down by 5. A delivery arrives, so it goes up by 20. Writing stock = stock - 5 every time works, but it's so common that Python has shorter versions. Each one does the maths and stores the result back in the same variable:
stock = 120
stock -= 5 # same as stock = stock - 5
stock += 20 # same as stock = stock + 20
stock *= 2 # same as stock = stock * 2
print(stock)
270
Converting between types
Data from files, forms, input() and .split() always arrives as text. You must convert it before doing maths, and Python won't do it for you:
quantity_text = "3"
print(quantity_text * 2)
print(int(quantity_text) * 2)
33
6
"3" * 2 doesn't fail, which makes it sneaky. Python sees a string times 2 and repeats it, giving "33", so a quantity of 3 becomes 33 without any error. Converting first with int() gives the 6 you actually wanted. These are the conversion functions you'll use:
int("42")turns text into an int.int(4.9)turns a float into an int by chopping off the decimals (giving4, not5).float("4.75")turns text into a float.str(95000)turns a number into text.
Conversion fails loudly when the text isn't a valid number:
print(int("4.5"))
ValueError: invalid literal for int() with base 10: '4.5'
int() only accepts whole-number text. To get an int from "4.5", go through float first: int(float("4.5")). And remove symbols first: int("Rp 95.000") fails until you strip out "Rp " and the dots, as you did in the last module.
Why this matters for clean code
Two habits prevent most number bugs. First, convert at the boundary: turn text into numbers the moment it enters your program, so everything after works with real numbers. Second, name the units: price_rupiah, duration_minutes, vat_rate. A variable called time could hold seconds, minutes or a date; duration_minutes can't be misread.
Recap
intfor whole numbers,floatfor decimals. Mixing them gives a float./always returns a float.//floor-divides,%gives the remainder.- Floats aren't exact: use
round()for results and avoid==on floats. abs,min,max,roundare built in;math.ceil,math.floorandmath.sqrtneedimport math.+=,-=,*=update a variable in place.- Convert with
int(),float()andstr(). Text from outside is always a string until you convert it.