Your country

Tools that support it use your country for local currency, number formats, units and paper size. Your choice is saved only in this browser.

Type a name or a two-letter code. Use the up and down arrow keys to move through the countries, Enter to choose one and Escape to close.

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().

  • Beginner
  • 20 minutes
  • Examples run with Python 3.14.8 and Pyodide 314.0.7
  • By MySmartCoPilot

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

Number literals Python · literals.py
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

  • Underscores between digits are ignored, so 1_000_000 is easier to read than 1000000 and means the same (PEP 515, Python 3.6). Only single underscores between digits are allowed: 1__000 and 1000_ are syntax errors.
  • 0b, 0o and 0x start binary, octal and hexadecimal numbers. A later lesson on number bases covers them.
  • A decimal point or an e makes a float. 2e3 means 2 × 10³, and it is the float 2000.0, not the int 2000.
  • A whole number other than zero cannot start with 0: 017 is a SyntaxError, and the message suggests the 0o prefix 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 * 5 gives 85.
  • / divides, and the result is always a float: 17 / 5 gives 3.4.
  • // divides and then rounds down to a whole number (floor division): 17 // 5 gives 3.
  • % gives the remainder that floor division leaves (modulo): 17 % 5 gives 2.
  • ** raises to a power: 17 ** 2 gives 289.
Every arithmetic operator once Python · arithmetic_tour.py
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

Three rules explain every result above:

  1. / always gives a float, even when the division comes out exact: 10 / 2 is 5.0. Use // when you need a whole number.
  2. An int and a float give a float. Python converts the int first, so 3 * 1.5 is 4.5 and 2 + 0.0 is 2.0. Two ints give an int with +, -, *, //, % and **, except that a negative power gives a float: 2 ** -1 is 0.5.
  3. ** is the power operator. ^ also exists, but it is the bitwise “exclusive or” of the two numbers’ bits, so 2 ^ 3 is 1, 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:

The middle of a list Python · middle_item.py
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

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.

A number line from -4 to 0 with -3.5 marked: floor division moves it down to -4, and int() of -7 / 2 moves it towards zero, to -3.-7 / 2 is -3.5-7 // 2 → -4floor: always down-4-3.5-3-2-10int(-7 / 2) → -3truncation: towards zero

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:

// and % for every combination of signs Python · floor_and_remainder.py
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

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:

Wrapping around and splitting into units Python · clock_maths.py
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

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:

Lakhs and paise Python · indian_amounts.py
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

Lakh Crore Converter (to Million, Billion) See a number with Indian and international grouping side by side, in words too.

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:

Big integers Python · big_numbers.py
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

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:

The 4,300-digit limit Python · digit_limit.py
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

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.

Big Number Calculator Work out powers and factorials with thousands of digits without writing a program.

Rounding

round(), int() and floor division Python · rounding.py
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

  • round(x) returns the nearest int, and a tie goes to the even neighbour: round(2.5) is 2, round(3.5) is 4 and round(-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 to n decimal places, and a negative n rounds to tens, hundreds and so on: round(1234, -2) is 1200.
  • int(x) drops the fractional part, so it rounds towards zero: int(-3.99) is -3. Compare -7 // 2, which is -4, with int(-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.

Rounding Calculator Compare round-half-to-even with the other rounding modes on your own numbers.

Key takeaways

  • int holds whole numbers of any size; float holds 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 ints a == b * (a // b) + a % b always 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, and int() 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.

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.

  1. Question 1 of 5 What is the value of -7 // 2?

    Type a number.

    Show the answer to question 1

    Answer: -4

    -7 / 2 is -3.5, and floor division rounds down, towards minus infinity, so the result is -4. Dropping the fraction instead, as int(-7 / 2) does, gives -3.

  2. Question 2 of 5 What does this print?

    Read the code, then choose one answer.

    print(-7 % 3)
    Show the answer to question 2

    Answer: 2

    -7 // 3 is -3 (rounded down from -2.33…), and -7 - 3 * -3 is 2. With a positive divisor the remainder is never negative: it has the sign of the number you divide by.

  3. Question 3 of 5 Which of these expressions give a float?

    Choose every answer that is right.

    Show the answer to question 3

    Answer:

    • 7 // 2.0
    • 2 ** -1
    • 8 / 4

    / always gives a float (2.0 here), a negative power gives a float (0.5), and floor division of a float gives a float (3.0). 7 // 2 is the int 3, 2 ** 10 the int 1024, and int(7.9) the int 7.

  4. Question 4 of 5 What does rounding.py print?

    What does this program print? Choose one answer.

    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
    Show the answer to question 4

    Answer: it prints

    2 4 -2
    2.57 1200
    3 -3
    -4 -3

    round() sends a tie to the even neighbour (2.5 → 2, 3.5 → 4, -2.5 → -2), and a negative number of places rounds to hundreds. int() drops the fraction, so int(-3.99) is -3, while -7 // 2 rounds down to -4.

  5. Question 5 of 5 x = 10 ** 5000 works, but str(x) raises a ValueError. Why?

    Choose one answer.

    Show the answer to question 5

    Answer: CPython refuses to convert ints of more than 4,300 decimal digits to text unless you raise the limit, because such conversions are slow

    Ints have no size limit, so computing 10 ** 5000 is exact. Converting between int and decimal text is slow for huge numbers, which a program reading untrusted input could be attacked with, so CPython limits it to 4,300 digits by default. Hexadecimal is not limited, and sys.set_int_max_str_digits() changes the limit.

References

Related tools

Report a problem with this lesson

Quick answers and tool search

Type to search tools or to get a quick answer, for example 18% of 2500. Use the up and down arrow keys to move through the results, Enter to choose, and Escape to close.