Index Ai Academy
Phase 0 · Tools · Python core

Numbers and arithmetic

Integers, decimals, rounding, and the math behind every metric.

About 20 minutes · Free lesson

Start this lesson

Why it matters

Machine learning is arithmetic at enormous scale. A model's prediction is a long chain of multiplications and additions. Its training "loss" is a single number. The probability, token count and dollar cost of every API call are numbers too. You already work with rates and ratios at work. This lesson shows how to make Python do it, and where its arithmetic can surprise you.

What you'll be able to do

  • Calculate with +, -, *, /, //, % and ** and predict the result
  • Control the order of a calculation with parentheses
  • Round results, and explain why 0.1 + 0.2 isn't exactly 0.3
  • Convert between text and numbers with int(), float() and str()

What it covers

  1. The arithmetic operators
  2. Order of operations
  3. Whole batches and what's left over
  4. Powers and rounding
  5. Converting between text and numbers
  6. Worked example: ROAS and CPA from exported text
  7. Results that surprise people

The arithmetic operators

OperatorMeaningExampleResult
+add1200 + 3401540
-subtract5000 - 3120.51879.5
*multiply2.5 * 4001000.0
/divide1920 / 240000.08
//divide, rounding down to a whole number2340 // 5004
%remainder after dividing2340 % 500340
**to the power of1.05 ** 31.157625
spend = 1250.50
clicks = 500
print("Cost per click:", spend / clicks)
print("Spend doubled:", spend * 2)
It runs right here in your browser, with nothing to install.

Python has two kinds of number:

  • Integers (int) are whole numbers, like 500.
  • Floats (float) have a decimal point, like 1250.5.

Mix them in a calculation, and the result is a float. Division with / always gives a float, even when it divides evenly:

print(10 / 2)
print(type(10 / 2))

Long numbers are easier to read with underscores, which Python ignores: impressions = 1_250_000.

Order of operations

Python follows the order you learned in school:

  1. ** first,
  2. then *, /, // and %,
  3. then + and -.

Operators at the same level go left to right. Parentheses override all of it. Use them whenever the order matters, even if you think Python would get it right anyway. They make your meaning obvious to the next reader.

revenue = 15840
cost = 3120.5

wrong_margin = revenue - cost / revenue     # divides first, then subtracts
margin = (revenue - cost) / revenue         # what we actually meant

print(wrong_margin)
print(margin)
Quick check
What does this print?
print(2 + 3 * 4)
  1. 24
  2. 14
  3. 234
  4. 20
Show the answer

14

Multiplication happens before addition: 3 * 4 is 12, plus 2 is 14. Write (2 + 3) * 4 if you want 20.

Whole batches and what's left over

// and % answer two questions that come up all the time: how many whole groups fit, and how many are left over. Think of packing eggs into boxes of 12. // counts the full boxes, and % counts the eggs left over.

Say an email platform sends in batches of 500:

Try it now

Step through and watch full_batches and left_over appear. The last calculation proves nothing was lost: 4 × 500 + 340 = 2340.

Quick check
You have 50 eggs and boxes that hold 12. What does 50 // 12 give, and what does 50 % 12 give?
  1. 4 and 0.17
  2. 4.17 and 0
  3. 2 and 4
  4. 4 and 2
Show the answer

4 and 2

Four full boxes use 48 eggs, so 50 // 12 is 4, and 2 eggs are left over, so 50 % 12 is 2.

Powers and rounding

** raises a number to a power. It's how you model compounding, such as a channel growing 5% a week:

weekly_signups = 1000
growth = 1.05
print(weekly_signups * growth ** 4)    # four weeks of 5% growth

round(number, digits) rounds to that many decimal places. With no second argument it rounds to a whole number and gives back an int:

ctr = 0.034782
print(round(ctr, 3))
print(round(ctr * 100, 1))   # as a percentage
print(round(1157.625))

Why 0.1 + 0.2 isn't 0.3

Try this:

print(0.1 + 0.2)

This isn't a bug in Python. Computers store floats in binary, using only 0s and 1s. Most decimal fractions, 0.1 included, can't be written exactly in binary. It's like how 1/3 can't be written exactly in decimal (0.3333...). Python stores the closest value it can, and tiny differences sometimes show up.

In practice:

  • Round when you display results. round(0.1 + 0.2, 2) is 0.3.
  • Don't expect two floats calculated differently to be exactly equal. You'll see how to compare them safely in the conditionals lesson.
  • Systems that handle money often store whole cents as integers to avoid the issue entirely.

Watch out: round() rounds an exact half to the nearest even number, so round(2.5) is 2 and round(3.5) is 4. It rarely matters for reporting, but it explains results that look off by one.

Converting between text and numbers

Data from a spreadsheet export, a web form or an API often arrives as text, even when it looks like a number. You saw in the last lesson that "5000" + 100 fails. Three functions convert between types:

FunctionConverts toExampleResult
int()whole numberint("42")42
float()decimal numberfloat("19.99")19.99
str()textstr(5000)"5000"
budget_text = "5000"          # text, perhaps read from a file
budget = int(budget_text)     # now a number
print(budget + 100)

price = float("19.99")
print(price * 3)

print("Clicks: " + str(120))  # + joins text, so the number must become text first

int() of a float drops the decimal part instead of rounding: int(3.9) is 3. And int() refuses text that isn't a clean whole number:

print(int("19.99"))

Use float("19.99") for text with a decimal point. Text such as "1,200" fails in both, because of the comma. The strings lesson shows how to remove it first.

Worked example

Worked example: ROAS and CPA from exported text

A spreadsheet export gives you a campaign's spend, revenue and conversions, all as text. Work out the return on ad spend (revenue ÷ spend) and the cost per acquisition (spend ÷ conversions), rounded to cents.

spend_text = "2390.75"
revenue_text = "3290"
conversions_text = "47"

spend = float(spend_text)
revenue = float(revenue_text)
conversions = int(conversions_text)

roas = revenue / spend
cpa = spend / conversions

print("ROAS:", round(roas, 2))
print("CPA:", round(cpa, 2))
In the lesson you can change this and run it.

Converting first and calculating second keeps each step simple. spend uses float() because it has cents. conversions is a count, so int() fits. The rounding happens only in the print lines, so roas and cpa keep their full detail for any later calculation. A ROAS of 1.38 means every dollar spent brought back $1.38 in revenue.

Quick check
What does this print?
print(int(7.8))
  1. 7
  2. 8
  3. An error
  4. 7.8
Show the answer

7

int() cuts off the decimal part. It doesn't round. Use round(7.8) to get 8.

Results that surprise people

A few of Python's arithmetic rules catch almost everyone once.

Division always gives a decimal. 10 / 2 is 5.0, not 5, even though the answer is whole. The type of result doesn't depend on the numbers you happened to use, which makes programs more predictable. If you want a whole number, use //.

int() cuts, it doesn't round. int(3.9) is 3. Python drops everything after the point. For a rounded answer, use round(3.9), which gives 4.

print(10 / 2)
print(int(3.9), round(3.9))

Order of operations still applies. Suppose revenue is 200 and cost is 150, and you want the margin. Writing revenue - cost / revenue gives 199.25, because the division happens first. What you meant needs brackets: (revenue - cost) / revenue, which gives 0.25. When a result looks odd, check the brackets before anything else.

int() is picky about text. int("42") works, but int("3.5") and int("twelve") stop with a ValueError. Text with a decimal point has to go through float() first. This matters as soon as your numbers come from a form or a file, because those always start out as text.

Practice what you just read

  • 10 code examples you can edit and run
  • a practice exercise that checks your code
  • a 6-question quiz
  • 6 review cards for spaced repetition

Start this lesson

Try a quiz question

What does this print?

print(2 + 3 * 2 ** 2)
  1. 14
  2. 20
  3. 100
  4. 25

Answer it at the end of the lesson to see if you're right, and why.

Before this lesson