Python Module 2 – Values, variables, numbers and strings
Integers, floats and arithmetic operators
Use Python's arithmetic operators on int and float: true and floor division, % with negative numbers, ** and divmod(), huge integers and round().
What you will learn
- Use +, -, *, /, //, % and ** with integers and floats
- Predict // and % results for negative numbers
- Explain arbitrary-precision integers and the integer string-conversion limit
Before you start
On this page
Python has two number types for everyday work. An int is a whole number such as 42, -7 or 0, and it can be
as large as your computer’s memory allows. A float is a number with a fractional part, such as 3.5 or 0.25,
stored in binary with 53 bits of precision, which is roughly 16 significant decimal digits. (A third type,
complex, for numbers such as 3+4j, is for maths and engineering; the later lesson on the math module comes back
to it.) This lesson covers the operators that do arithmetic with both, and the few places where they behave
differently from a pocket calculator.
Writing numbers
print(1_000_000) # underscores make long numbers easier to read
print(0b1010, 0o17, 0xFF) # binary, octal and hexadecimal literals
print(2e3, 1.5e-3) # e notation always gives a float
print(type(2e3), type(2_000)) Output
1000000 10 15 255 2000.0 0.0015 <class 'float'> <class 'int'>
Recorded with Python 3.14.8 on macOS 26 arm64. To run it yourself: mise exec python@3.14.8 -- python3 literals.py
Runs on this device, in your browser. The first run downloads Python (about 13.5 MB), which is kept for the next runs.
Your run, in this browser
- Underscores between digits are ignored, so
1_000_000is easier to read than1000000and means the same (PEP 515, Python 3.6). Only single underscores between digits are allowed:1__000and1000_are syntax errors. 0b,0oand0xstart binary, octal and hexadecimal numbers. A later lesson on number bases covers them.- A decimal point or an
emakes a float.2e3means 2 × 10³, and it is the float2000.0, not the int2000. - A whole number other than zero cannot start with 0:
017is aSyntaxError, and the message suggests the0oprefix in case you meant octal. Phone numbers, PIN codes and other identifiers with leading zeros are text, not numbers; keep them as strings.
The arithmetic operators
+,-and*add, subtract and multiply:17 * 5gives85./divides, and the result is always a float:17 / 5gives3.4.//divides and then rounds down to a whole number (floor division):17 // 5gives3.%gives the remainder that floor division leaves (modulo):17 % 5gives2.**raises to a power:17 ** 2gives289.
a, b = 17, 5
print(a + b, a - b, a * b)
print(a / b) # true division: always a float
print(a // b) # floor division
print(a % b) # the remainder
print(a ** 2) # a power
print(10 / 2) # a float, even when the division is exact
print(3 * 1.5, 2 + 0.0) # an int and a float give a float
print(2 ** 0.5, 2 ** -1) # fractional and negative powers give floats
print(2 ^ 3) # careful: ^ is not a power in Python Output
22 12 85 3.4 3 2 289 5.0 4.5 2.0 1.4142135623730951 0.5 1
Recorded with Python 3.14.8 on macOS 26 arm64. To run it yourself: mise exec python@3.14.8 -- python3 arithmetic_tour.py
Runs on this device, in your browser. The first run downloads Python (about 13.5 MB), which is kept for the next runs.
Your run, in this browser
Three rules explain every result above:
/always gives a float, even when the division comes out exact:10 / 2is5.0. Use//when you need a whole number.- An int and a float give a float. Python converts the int first, so
3 * 1.5is4.5and2 + 0.0is2.0. Two ints give an int with+,-,*,//,%and**, except that a negative power gives a float:2 ** -1is0.5. **is the power operator.^also exists, but it is the bitwise “exclusive or” of the two numbers’ bits, so2 ^ 3is1, not 8. Spreadsheet formulas write powers with^, which makes this an easy mistake.
A common mistake: / where a whole number is needed
A list position must be an int. A float from / is not one, even when it happens to be 2.0:
names = ["Asha", "Ben", "Chen", "Dev", "Esi"]
middle = len(names) / 2
print(middle)
print(names[middle]) Output (exit status 1)
2.5
Printed as an error (standard error)
Traceback (most recent call last):
File "middle_item.py", line 4, in <module>
print(names[middle])
~~~~~^^^^^^^^
TypeError: list indices must be integers or slices, not float
Recorded with Python 3.14.8 on macOS 26 arm64. To run it yourself: mise exec python@3.14.8 -- python3 middle_item.py
Runs on this device, in your browser. The first run downloads Python (about 13.5 MB), which is kept for the next runs.
Your run, in this browser
len(names) // 2 gives 2, and names[2] is "Chen". When the length is even, // picks the second of the two
middle positions; decide whether that is what you want.
Floor division and the remainder with negative numbers
a // b does the division and then rounds down, towards minus infinity. For positive numbers that simply drops
the fraction, but for a negative result it is one less than you might expect: -7 / 2 is -3.5, so -7 // 2 is
-4. Many languages, Java among them, round integer division towards zero instead and would give -3.
Two ways to make a whole number of -3.5
Text description of the diagram
A number line shows the whole numbers -4, -3, -2, -1 and 0, with the exact result of -7 / 2, which is -3.5, marked between -4 and -3.
- Above the line, an arrow goes from -3.5 to the left, to -4: floor division, -7 // 2, always rounds down, towards minus infinity.
- Below the line, an arrow goes from -3.5 to the right, to -3: int(-7 / 2) drops the fraction, which moves the value towards zero. Java, for example, rounds its integer division this way.
For positive results the two agree: 7 // 2 and int(7 / 2) are both 3.
a % b is whatever floor division leaves over, so the two are tied together by one rule that always holds for
ints: a == b * (a // b) + a % b. A consequence is that the remainder has the same sign as b, the number you
divide by, or is 0:
print(" a b a // b a % b check")
for a in (7, -7):
for b in (2, -2):
check = b * (a // b) + a % b # always gives a back
print(f"{a:2} {b:2} {a // b:6} {a % b:5} {check:5}")
print(divmod(-7, 2)) # both results at once: (a // b, a % b) Output
a b a // b a % b check 7 2 3 1 7 7 -2 -4 -1 7 -7 2 -4 1 -7 -7 -2 3 -1 -7 (-4, 1)
Recorded with Python 3.14.8 on macOS 26 arm64. To run it yourself: mise exec python@3.14.8 -- python3 floor_and_remainder.py
Runs on this device, in your browser. The first run downloads Python (about 13.5 MB), which is kept for the next runs.
Your run, in this browser
Read the rows as predictions you can check. The check column works out b * (a // b) + a % b, and it gives back
a every time. divmod(a, b) returns both results at once, as the pair (a // b, a % b).
Why rounding down is useful
With a positive divisor, % never returns a negative number, so it is ideal for anything that wraps around, such
as days of the week. And divmod(), which gives the quotient and the remainder together, is the natural tool for
splitting an amount into units:
days = ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"]
today = 0 # Monday
print("In 10 days:", days[(today + 10) % 7])
print("3 days ago:", days[(today - 3) % 7]) # -3 % 7 is 4, never negative
total = 7384 # seconds
minutes, seconds = divmod(total, 60)
hours, minutes = divmod(minutes, 60)
print(hours, "h", minutes, "min", seconds, "s") Output
In 10 days: Thu 3 days ago: Fri 2 h 3 min 4 s
Recorded with Python 3.14.8 on macOS 26 arm64. To run it yourself: mise exec python@3.14.8 -- python3 clock_maths.py
Runs on this device, in your browser. The first run downloads Python (about 13.5 MB), which is kept for the next runs.
Your run, in this browser
Three days before Monday (position 0) is position -3 % 7, which is 4, Friday, with no special case for going
back past the start of the week. Python’s programming FAQ gives the same reason for the design: when the divisor is
positive, a remainder that is never negative is almost always the one you want.
India-specific
Because Python ignores the underscores in a number, it accepts Indian digit grouping too: 1_00_000 is one lakh
and 1_00_00_000 one crore. The , option of Python’s number formatting groups digits in threes, though. Money
is safest counted in paise, as an int, and divmod() splits it back into rupees and paise:
amount = 1_00_000 # one lakh, grouped the Indian way
print(amount)
print(f"{amount:,}") # the , option groups digits in threes
rupees, paise = divmod(12_345, 100) # 12,345 paise
print(rupees, "rupees and", paise, "paise") Output
100000 100,000 123 rupees and 45 paise
Recorded with Python 3.14.8 on macOS 26 arm64. To run it yourself: mise exec python@3.14.8 -- python3 indian_amounts.py
Runs on this device, in your browser. The first run downloads Python (about 13.5 MB), which is kept for the next runs.
Your run, in this browser
Integers have no size limit
In many languages an integer has a fixed size, such as 64 bits, and a calculation that goes past the limit overflows. Python’s ints grow as needed, so adding, subtracting, multiplying, floor-dividing and raising them to powers that are not negative is always exact:
import sys
print(2 ** 100)
print(len(str(2 ** 1000)), "digits in 2 ** 1000")
print(sys.maxsize) # the largest size a list or a string can have, not the largest int
print(sys.maxsize + 1) # no overflow: an int simply grows Output
1267650600228229401496703205376 302 digits in 2 ** 1000 9223372036854775807 9223372036854775808
Recorded with Python 3.14.8 on macOS 26 arm64. To run it yourself: mise exec python@3.14.8 -- python3 big_numbers.py
Runs on this device, in your browser. The first run downloads Python (about 13.5 MB), which is kept for the next runs.
Your run, in this browser
sys.maxsize is not the largest int. It is the largest value of Py_ssize_t, the C type CPython uses for the size
of a list or a string and for positions in it (PEP 353), and adding 1 to it works like any other addition.
Version note
In your browser, Python runs as 32-bit WebAssembly, so sys.maxsize there is 2147483647 (2³¹ − 1) instead of the
64-bit value 9223372036854775807 (2⁶³ − 1). The int arithmetic itself gives the same results everywhere.
In your browser, Pyodide 314.0.7 (CPython 3.14.2) prints:
1267650600228229401496703205376 302 digits in 2 ** 1000 2147483647 2147483648
The digit limit for converting to text
Python lets you compute with ints of any size, but turning one into decimal digits, with str(), print() or an
f-string, or reading digits with int(), takes time that grows faster than the number of digits. A program that
accepts a number from a user could be stalled by one with millions of digits, so CPython refuses conversions of more
than 4,300 decimal digits by default:
import sys
big = 10 ** 5000 # computing with a huge int is fine
print(big.bit_length(), "bits")
try: # try and except catch the error so that the program can go on
text = str(big) # turning it into decimal text is limited
except ValueError as error:
print("ValueError:", error)
print(len(hex(big)), "characters in hexadecimal") # no limit for hex
sys.set_int_max_str_digits(6000) # raise the limit, for this program only
print(len(str(big)), "decimal digits") Output
16610 bits ValueError: Exceeds the limit (4300 digits) for integer string conversion; use sys.set_int_max_str_digits() to increase the limit 4155 characters in hexadecimal 5001 decimal digits
Recorded with Python 3.14.8 on macOS 26 arm64. To run it yourself: mise exec python@3.14.8 -- python3 digit_limit.py
Runs on this device, in your browser. The first run downloads Python (about 13.5 MB), which is kept for the next runs.
Your run, in this browser
The try and except lines (the module on errors explains them) catch the ValueError so that the program can go
on. Hexadecimal and binary conversions are not limited, and sys.set_int_max_str_digits() raises the limit for the
rest of the program, as the last two lines show; 0 would remove it. Raise it only in programs that never convert
numbers that come from outside, such as a web form or an uploaded file.
Rounding
print(round(2.5), round(3.5), round(-2.5)) # a tie goes to the even neighbour
print(round(2.567, 2), round(1234, -2)) # to 2 decimal places; to the nearest hundred
print(int(3.99), int(-3.99)) # int() drops the fraction
print(-7 // 2, int(-7 / 2)) # floor division and dropping the fraction differ Output
2 4 -2 2.57 1200 3 -3 -4 -3
Recorded with Python 3.14.8 on macOS 26 arm64. To run it yourself: mise exec python@3.14.8 -- python3 rounding.py
Runs on this device, in your browser. The first run downloads Python (about 13.5 MB), which is kept for the next runs.
Your run, in this browser
round(x)returns the nearest int, and a tie goes to the even neighbour:round(2.5)is2,round(3.5)is4andround(-2.5)is-2. Over many values, about half of the ties go up and half go down, so a total of rounded numbers does not drift upwards the way it does when every .5 is rounded up.round(x, n)rounds tondecimal places, and a negativenrounds to tens, hundreds and so on:round(1234, -2)is1200.int(x)drops the fractional part, so it rounds towards zero:int(-3.99)is-3. Compare-7 // 2, which is-4, withint(-7 / 2), which is-3.
Rounding a float to a number of decimal places, as in round(2.675, 2), holds one more surprise, which the next
lesson explains.
Key takeaways
intholds whole numbers of any size;floatholds fractions in binary, with roughly 16 significant digits./always returns a float;//rounds down to a whole number and%gives the remainder;**is the power operator, and^is not.- Floor division rounds towards minus infinity, so
-7 // 2 == -4, and for intsa == b * (a // b) + a % balways holds; the remainder takes the sign of the divisor. - Mixing an int and a float gives a float; a list position must be an int.
- CPython refuses int and string conversions longer than 4,300 decimal digits unless you raise the limit.
round()sends ties to the even neighbour, andint()rounds towards zero.
Exercise
Exercise · Easy · Python
Split a bill fairly, to the last paisa
Friends share a bill, and the app that splits it counts money in whole paise (100 paise make one rupee; the same code works for cents). Write split_amount(total_paise, people), which returns a list with one share per person:
- the shares add up to exactly
total_paise, so not a single paisa is lost or invented; - no two shares differ by more than 1 paisa;
- the larger shares come first.
For example, split_amount(10000, 3) returns [3334, 3333, 3333], and split_amount(2, 5) returns [1, 1, 0, 0, 0]. When people is less than 1, or total_paise is negative, raise ValueError.
Use divmod(): its first result is what everyone pays, and its second says how many people pay one paisa more.
Starter code · split.py
def split_amount(total_paise, people):
"""Return one share per person, in paise: they add up to total_paise and differ by at most 1."""
# Replace this line with your code.
return [] The sample tests · test_split.py
from split import split_amount
def raises_value_error(total_paise, people):
"""True when split_amount(total_paise, people) raises ValueError."""
try:
split_amount(total_paise, people)
except ValueError:
return True
return False
def test_even_split():
"""splits evenly when the total divides exactly"""
assert split_amount(900, 3) == [300, 300, 300]
def test_extra_paise_first():
"""gives the paise that are left over to the first shares"""
assert split_amount(10000, 3) == [3334, 3333, 3333]
assert split_amount(10001, 3) == [3334, 3334, 3333]
def test_fair_and_complete():
"""always returns one share per person, adding up to the total, at most 1 paisa apart"""
for total, people in [(10000, 3), (12345, 7), (1, 4), (999, 10), (250000, 6)]:
shares = split_amount(total, people)
assert len(shares) == people
assert sum(shares) == total
assert max(shares) - min(shares) <= 1
def test_one_person():
"""lets one person pay everything"""
assert split_amount(4999, 1) == [4999]
def test_zero_total():
"""gives everyone 0 when the bill is 0"""
assert split_amount(0, 4) == [0, 0, 0, 0]
def test_fewer_paise_than_people():
"""gives some people 0 when there are fewer paise than people"""
assert split_amount(2, 5) == [1, 1, 0, 0, 0]
def test_bad_input():
"""raises ValueError for fewer than one person or a negative total"""
assert raises_value_error(100, 0)
assert raises_value_error(100, -2)
assert raises_value_error(-5, 2) A hint
divmod(10000, 3) is (3333, 1): everyone pays 3333 paise and one person pays one more. Lists can be built with operators too: [7] * 3 is [7, 7, 7], and + joins two lists, so [3334] * 1 + [3333] * 2 is the answer for this example. For the errors, raise ValueError("…") stops the function with that message.
Results of the sample tests
| Test | Result | Details |
|---|
What your code printed
The sample tests run on this device, in your browser (Pyodide): nothing is sent to mysmartcopilot.com. The first run downloads Python (about 13.5 MB), which is kept for the next runs. A check in your browser is feedback for you, not proof that the code is right for every input.
Check yourself
5 questions about this lesson. Every answer and why it is right is on the page, behind “Show the answer”. Your score stays in this browser.
References
- The Python Tutorial: numbers (Python Software Foundation)
- Numeric types, int, float and complex (Python Software Foundation)
- Binary arithmetic operations (Python Software Foundation)
- The power operator (Python Software Foundation)
- Numeric literals (Python Software Foundation)
- Integer string conversion length limitation (Python Software Foundation)
- Built-in functions, round() (Python Software Foundation)
- Built-in functions, divmod() (Python Software Foundation)
- sys.maxsize (Python Software Foundation)
- Programming FAQ: why does -22 // 10 return -3? (Python Software Foundation)
- PEP 515: Underscores in Numeric Literals (Python Software Foundation)
- PEP 353: Using ssize_t as the index type (Python Software Foundation)
- The Java Language Specification, Java SE 25: the division operator (Oracle)
Related tools
Report a problem with this lesson
Kept only in this browser. Your Learn progress