Numbers & Math

Python · Lesson 7 of 43 7 min read Updated

Almost every program does some maths: a bill total, an average, a percentage, the number of buses needed for a school trip. Python handles numbers well, but it has a few behaviours that surprise beginners, especially around division, rounding and decimal values like money.

In this lesson you will learn Python's number types, the arithmetic operators, how rounding really works, how to handle rupees and paise correctly with the decimal module, and the most useful functions in the math module.

Three kinds of numbers

Python has three built-in number types:

  • int: whole numbers such as 42, -7 or 0. They can be as large as your memory allows.
  • float: numbers with a decimal point, such as 3.14 or 1299.50.
  • complex: complex numbers such as 3+4j, used in engineering and science.
PythonRun it yourself
population = 1_00_00_000      # underscores are ignored, so this is one crore
price = 1299.50
big = 2 ** 100

print(population)
print(type(price))
print(big)
Output
10000000
<class 'float'>
1267650600228229401496703205376

You can put underscores between digits to make long numbers readable, and Python ignores them. They can go anywhere between digits, so the Indian lakh and crore grouping works fine. Notice also that 2 ** 100 gives the exact answer: Python integers never overflow.

Arithmetic operators

OperatorMeaningExampleResult
+Add7 + 29
-Subtract7 - 25
*Multiply7 * 214
/Divide7 / 23.5
//Integer (floor) division7 // 23
%Remainder (modulo)7 % 21
**Power7 ** 249

The plain / always gives a float, even when the division is exact: 10 / 2 is 5.0. Use // when you want a whole-number answer. The // and % operators are a team: one tells you how many times something fits, the other tells you what is left over.

PythonRun it yourself
laddoos = 17
children = 5

each = laddoos // children
left_over = laddoos % children
print("Each child gets", each, "and", left_over, "are left")

print(divmod(laddoos, children))
print("Is 17 even?", laddoos % 2 == 0)
Output
Each child gets 3 and 2 are left
(3, 2)
Is 17 even? False

The built-in divmod() gives both answers at once. And % 2 == 0 is the standard test for an even number.

With negative numbers, // rounds down towards minus infinity, not towards zero, so -17 // 5 is -4 and -17 % 5 is 3. You rarely need this, but it explains a surprising result if you see one.

Floats are not exact

Computers store floats in binary, and many decimal fractions, such as 0.1, cannot be stored exactly. Tiny errors appear:

PythonRun it yourself
import math

print(0.1 + 0.2)
print(0.1 + 0.2 == 0.3)
print(math.isclose(0.1 + 0.2, 0.3))
Output
0.30000000000000004
False
True

This is not a Python bug; every language that uses standard floats behaves this way. Never compare floats with ==. Use math.isclose() instead, which allows for tiny differences.

Rounding with round()

round(number, digits) rounds to a number of decimal places. With no second argument it rounds to a whole number. A negative second argument rounds to tens, hundreds and so on.

PythonRun it yourself
print(round(1234.5678, 2))
print(round(1234.5678, -2))
print(round(2.5), round(3.5), round(4.5))
print(round(2.675, 2))
Output
1234.57
1200.0
2 4 4
2.67

Two results need explaining:

  • round(2.5) is 2, not 3. When a number is exactly halfway, Python rounds to the nearest even number. This is called banker's rounding, and it avoids pushing totals upwards when you round many values.
  • round(2.675, 2) is 2.67. The float 2.675 is really stored as 2.67499999..., so it rounds down.

Money: use decimal

Because floats are not exact, they are a poor choice for money. Python's decimal module stores decimal numbers exactly. Create a Decimal from a string, not from a float.

PythonRun it yourself
from decimal import Decimal, ROUND_HALF_UP

price = Decimal("1299")
gst_rate = Decimal("0.18")

gst = price * gst_rate
total = price + gst
print("GST:", gst)
print("Total: ₹", total)

amount = Decimal("2.675")
print(amount.quantize(Decimal("0.01"), rounding=ROUND_HALF_UP))
Output
GST: 233.82
Total: ₹ 1532.82
2.68

quantize(Decimal("0.01")) rounds to two decimal places, that is, to paise. Passing rounding=ROUND_HALF_UP gives the "school" rounding most bills use, where 0.5 always goes up. Without it, Decimal also uses banker's rounding.

The math module

The math module has the functions you remember from school maths. You import it once at the top of the file, then use math. before each name. You will learn more about importing in Modules & Imports.

PythonRun it yourself
import math

students = 130
seats_per_bus = 40

print("Buses needed:", math.ceil(students / seats_per_bus))
print(math.floor(7.8), math.sqrt(144), math.pi)
print(math.gcd(48, 36), math.factorial(5), math.prod([2, 3, 4]))
print(abs(-250), max(78, 91, 85), min(78, 91, 85))
Output
Buses needed: 4
7 12.0 3.141592653589793
12 120 24
250 91 78

math.ceil() rounds up and math.floor() rounds down, which is exactly what you need for the bus question: 3.25 buses means you must book 4. abs(), max(), min(), sum() and pow() are built in, so they need no import.

Complex numbers have their own uses. A complex number has a real part and an imaginary part written with j: for z = 3+4j, z.real is 3.0, z.imag is 4.0, and abs(z) is 5.0.

Common mistakes

  • Expecting / to give an int. 10 / 2 is 5.0. Use // for whole-number results.
  • Using ^ for power. In Python ^ means something else (bitwise XOR), so 2 ^ 3 is 1. Use 2 ** 3.
  • Using floats for money. Small errors add up across thousands of bills. Use Decimal with string values.
  • Expecting round(2.5) to be 3. Python uses banker's rounding. Use Decimal with ROUND_HALF_UP when you need 0.5 to always round up.

Key points

  • int is for whole numbers (no size limit), float for decimals, complex for complex numbers.
  • / always returns a float; // gives the whole-number part and % the remainder.
  • Floats are not exact: compare them with math.isclose(), not ==.
  • round() uses banker's rounding: halfway values go to the nearest even number.
  • Use decimal.Decimal("...") for money and quantize() to round to paise.
  • import math gives ceil, floor, sqrt, pi, gcd, factorial, prod and more.

Exercise

A school in Pune is taking 245 students on a trip. Each bus holds 50 students and costs ₹4,750. Write a program that prints the number of buses needed, how many seats will be empty, and the total bus cost. Then work out the cost per student as a Decimal, rounded to paise with ROUND_HALF_UP.

Show solution
Python
import math
from decimal import Decimal, ROUND_HALF_UP

students = 245
seats = 50
bus_cost = 4750

buses = math.ceil(students / seats)
empty = buses * seats - students
total = buses * bus_cost
print("Buses:", buses, "Empty seats:", empty, "Total: ₹", total)

per_student = Decimal(total) / Decimal(students)
print("Per student: ₹", per_student.quantize(Decimal("0.01"), rounding=ROUND_HALF_UP))
Output
Buses: 5 Empty seats: 5 Total: ₹ 23750
Per student: ₹ 96.94

math.ceil() rounds 4.9 buses up to 5. Decimal(total) is safe because total is an int, and quantize() rounds the result to two decimal places.

Quick Quiz

1. What is 17 // 5?

2. What does round(2.5) return in Python?

3. Which is the safest way to store a price of ₹19.99?

4. How do you calculate 3 to the power of 4?

Learn Python with a mentor

Free lessons get you started. Our Python Programming training adds real projects and code reviews from working developers.

  • Project-based learning
  • Mentor code reviews
  • Free counselling call