Python Numbers & Arithmetic
Python has two primary numeric types: integers (int) for whole numbers and floats (float) for numbers with a decimal point. A third type, complex (for example 3 + 4j), exists for engineering and scientific work but is rarely needed day to day.
At a Glance
Section titled “At a Glance”| Task | Tool | Example |
|---|---|---|
| Basic math | +, -, *, / | 7 / 2 gives 3.5 |
| Whole-number division | // | 7 // 2 gives 3 |
| Remainder | % | 7 % 2 gives 1 |
| Power | ** | 2 ** 3 gives 8 |
| Update a variable | +=, -=, *=, … | count += 1 |
| Convert | int(), float() | int('45') gives 45 |
| Round | round(n, digits) | round(4.253, 1) gives 4.3 |
| Quotient and remainder together | divmod(a, b) | divmod(17, 5) gives (3, 2) |
| Advanced math | import math | math.sqrt(16) gives 4.0 |
Core Numeric Types
Section titled “Core Numeric Types”- Integer (
int): whole numbers, positive or negative (56,-4,0). - Float (
float): numbers with a decimal point (3.14,-12.0,0.0).
population = 8_100_000_000 # Underscores improve readabilitytemperature = -4.5scientific = 1.5e3 # 1500.0, scientific notation always gives a float
print(2 ** 100) # 1267650600228229401496703205376, ints never overflowprint(0b101, 0o17, 0xff) # 5 15 255, binary, octal, and hex literalsMixed Types Promote to Float
Section titled “Mixed Types Promote to Float”If you mix an int and a float in an operation, Python converts the result to a float. Standard division (/) always returns a float, even when dividing two integers evenly.
| Expression | Result | Type |
|---|---|---|
5 + 3 | 8 | int |
5 + 3.0 | 8.0 | float |
10 / 2 | 5.0 | float |
10 // 2 | 5 | int |
2 ** -1 | 0.5 | float |
Arithmetic Operators
Section titled “Arithmetic Operators”| Operator | Operation | Example | Result |
|---|---|---|---|
+ | Addition | 7 + 2 | 9 |
- | Subtraction | 7 - 2 | 5 |
* | Multiplication | 7 * 2 | 14 |
/ | True division (always a float) | 7 / 2 | 3.5 |
// | Floor division | 7 // 2 | 3 |
% | Modulo (remainder) | 7 % 2 | 1 |
** | Exponentiation | 7 ** 2 | 49 |
-x | Negation | -(7) | -7 |
Floor Division and Modulo
Section titled “Floor Division and Modulo”// divides and rounds down to the nearest whole number. % returns what is left over. Together they satisfy the identity a == (a // b) * b + a % b.
print(17 // 5) # 3, how many times 5 fits into 17print(17 % 5) # 2, what remainsprint(divmod(17, 5)) # (3, 2), both at once
print(7.5 // 2) # 3.0, with floats the result is still a floatprint(-7 // 2) # -4, rounds down toward negative infinity, not toward zeroprint(-7 % 3) # 2, the result takes the sign of the right-hand numberCommon uses for modulo:
number = 14
print(number % 2 == 0) # True, even number checkprint(number % 7 == 0) # True, divisibility checkprint((23 + 5) % 24) # 4, wrap-around (5 hours after 23:00 is 04:00)Powers and Roots
Section titled “Powers and Roots”print(2 ** 3) # 8print(2 ** -1) # 0.5print(16 ** 0.5) # 4.0, a fractional exponent gives a rootDivision by Zero
Section titled “Division by Zero”Dividing by zero with /, //, or % raises a ZeroDivisionError. Guard against it when the divisor comes from user input or calculations.
divisor = 0
if divisor != 0: print(10 / divisor)else: print('Cannot divide by zero') # RunsOperator Precedence
Section titled “Operator Precedence”Python follows the standard order of operations. Operators on the same level are evaluated left to right, with one exception: ** is evaluated right to left.
| Priority | Operators |
|---|---|
| 1 (highest) | Parentheses () |
| 2 | ** |
| 3 | Unary -x, +x |
| 4 | *, /, //, % |
| 5 (lowest) | +, - |
print(2 + 3 * 4) # 14, multiplication firstprint((2 + 3) * 4) # 20, parentheses overrideprint(2 ** 3 ** 2) # 512, evaluated as 2 ** (3 ** 2)print(-2 ** 2) # -4, evaluated as -(2 ** 2)print((-2) ** 2) # 4print(10 - 2 - 3) # 5, left to rightAugmented Assignment
Section titled “Augmented Assignment”Augmented assignment is shorthand for updating a variable: variable operator= value means variable = variable operator value.
| Operator | Equivalent to | Example | Result |
|---|---|---|---|
+= | x = x + n | count = 14; count += 3 | 17 |
-= | x = x - n | count = 14; count -= 3 | 11 |
*= | x = x * n | count = 14; count *= 2 | 28 |
/= | x = x / n | price = 100; price /= 4 | 25.0 (always a float) |
//= | x = x // n | count = 14; count //= 4 | 3 |
%= | x = x % n | bits = 35; bits %= 2 | 1 |
**= | x = x ** n | power = 2; power **= 3 | 8 |
total = 0
total += 10 # 10total += 5 # 15total *= 2 # 30total -= 4 # 26
print(total) # 26Built-in Numeric Functions
Section titled “Built-in Numeric Functions”| Function | Purpose | Example | Result |
|---|---|---|---|
int(x) | Convert to an integer, truncating decimals toward zero | int(12.925) | 12 |
int(x) | Parse a numeric string | int('45') | 45 |
float(x) | Convert to a float | float(56) | 56.0 |
float(x) | Parse a numeric string | float('7.8') | 7.8 |
round(x) | Round to the nearest integer | round(4.798) | 5 |
round(x, n) | Round to n decimal places | round(4.253, 1) | 4.3 |
abs(x) | Absolute value | abs(-15) | 15 |
pow(b, e) | Same as b ** e | pow(2, 3) | 8 |
pow(b, e, m) | Efficient (b ** e) % m | pow(2, 3, 5) | 3 |
divmod(a, b) | Quotient and remainder as a tuple | divmod(17, 5) | (3, 2) |
min() / max() | Smallest or largest value | max(4, 9, 2) | 9 |
sum(items) | Total of an iterable | sum([1, 2, 3]) | 6 |
Details Worth Knowing
Section titled “Details Worth Knowing”# int() truncates toward zero. It does not round.print(int(3.9)) # 3print(int(-3.9)) # -3
# int() cannot parse a decimal string directlyprint(int('3.5')) # ValueErrorprint(int(float('3.5'))) # 3
# round() uses "banker's rounding": halves go to the nearest even numberprint(round(2.5)) # 2print(round(3.5)) # 4
# A negative digits value rounds to tens, hundreds, and so onprint(round(1234, -2)) # 1200
# Parsing numbers in other basesprint(int('ff', 16)) # 255print(int('101', 2)) # 5The math Module
Section titled “The math Module”Modules are covered in more detail in the Modules & Packages section.
For roots, rounding up or down, and constants, import the standard math module.
import math
print(math.sqrt(16)) # 4.0print(math.floor(3.7)) # 3, rounds downprint(math.ceil(3.2)) # 4, rounds upprint(math.floor(-3.5)) # -4print(math.ceil(-3.5)) # -3print(math.trunc(-3.9)) # -3, drops the decimalsprint(math.pi) # 3.141592653589793print(math.isclose(0.1 + 0.2, 0.3)) # TrueFloating-Point Precision
Section titled “Floating-Point Precision”Computers store floats as binary approximations, and some decimal fractions cannot be represented exactly.
print(0.1 + 0.2) # 0.30000000000000004print(0.1 + 0.2 == 0.3) # Falseprint(round(2.675, 2)) # 2.67, not 2.68, because 2.675 is stored as 2.67499999...This is not a Python bug. It is how floating-point numbers work in every mainstream language. Choose the fix that fits your situation:
Use math.isclose() instead of ==.
import math
print(math.isclose(0.1 + 0.2, 0.3)) # TrueRound only when showing the value. Keep full precision internally.
total = 0.1 + 0.2print(f'{total:.2f}') # 0.30Use Decimal for exact decimal arithmetic. Always build it from a string, not a float.
from decimal import Decimal
print(Decimal('0.1') + Decimal('0.2')) # 0.3print(Decimal(0.1)) # 0.1000000000000000055511151231257827..., avoid thisConverting and Calculating Safely
Section titled “Converting and Calculating Safely”-
Clean incoming values. Data from
input(), files, and APIs arrives as strings. Convert it withint()orfloat(), and handleValueError. -
Choose the right operator. Use
/for exact quotients,//for whole-number results, and%for remainders. -
Update in place. Use
+=,*=, and friends to avoid repeating variable names. -
Round at the end. Keep full precision during calculations and round only for display.
raw_quantity = '45.5'
try: quantity = float(raw_quantity)except ValueError: print(f'{raw_quantity!r} is not a valid number')else: print(f'Half of {quantity} is {quantity / 2}') # Half of 45.5 is 22.75Worked Examples
Section titled “Worked Examples”# Average of a listscores = [88, 92, 79]average = sum(scores) / len(scores)print(f'Average: {average:.2f}') # Average: 86.33
# Applying a discountprice = 80discounted = round(price * 0.85, 2)print(discounted) # 68.0
# Converting seconds to hours, minutes, secondstotal_seconds = 3725hours, remainder = divmod(total_seconds, 3600)minutes, seconds = divmod(remainder, 60)print(f'{hours}h {minutes}m {seconds}s') # 1h 2m 5sCommon Mistakes
Section titled “Common Mistakes”| Mistake | Problem | Fix |
|---|---|---|
0.1 + 0.2 == 0.3 | Floating-point approximation | math.isclose(a, b) |
int(3.9) expecting 4 | Truncates, does not round | round(3.9) |
int('3.5') | ValueError | int(float('3.5')) |
-2 ** 2 expecting 4 | ** binds tighter than unary minus | (-2) ** 2 |
10 / 2 expecting 5 | / always returns a float (5.0) | 10 // 2 |
-7 // 2 expecting -3 | Floors toward negative infinity | int(-7 / 2) to truncate |
'Age: ' + 26 | TypeError, cannot add str and int | f'Age: {26}' |
x / 0 | ZeroDivisionError | Check the divisor first |
round(2.5) expecting 3 | Banker’s rounding gives 2 | Use Decimal with an explicit rounding mode when exact halves matter |
| Using floats for money | Rounding drift | Decimal('19.99') |
Best Practices Checklist
Section titled “Best Practices Checklist”- Use
//and%when you need whole-number results, and/when you need exact quotients. - Add parentheses to any expression where precedence is not obvious.
- Never compare floats with
==. Usemath.isclose(). - Use
Decimal, built from strings, for money and other exact decimal values. - Keep full precision while calculating, and round only for display.
- Wrap conversions of untrusted input in
try/except ValueError. - Guard divisions where the divisor might be zero.
- Use augmented assignment (
+=,*=) for clearer, shorter updates.