How to use modulo in Python

Learn how to use the modulo operator in Python. Discover different methods, real-world applications, tips, and how to debug common errors.

How to use modulo in Python
Published on: 
Fri
Feb 13, 2026
Updated on: 
Mon
Apr 13, 2026
The Replit Team

The modulo operator, %, is a simple yet powerful tool in Python that finds the remainder of a division. It's essential for tasks that require cyclical or patterned logic.

Here, you’ll explore key techniques, real-world applications, and debugging advice. You will gain practical tips to help you master the modulo operator for your specific use case.

Using the % operator for modulo division

a = 10
b = 3
remainder = a % b
print(f"{a} % {b} = {remainder}")
print(15 % 4)
print(8 % 2)--OUTPUT--10 % 3 = 1
3
0

The code puts the % operator to work, showing its fundamental behavior. In the first example, 10 % 3 correctly yields 1, which is the remainder left after dividing 10 by 3. The next examples highlight its versatility:

  • 15 % 4 returns 3, the amount remaining after the division.
  • 8 % 2 results in 0. This outcome is particularly useful, as a zero remainder is a classic way to test for divisibility—for instance, checking if a number is even.

Common modulo applications

Building on that divisibility check, you can use the % operator for many common tasks in programming and AI coding, like creating cycles or isolating digits from a larger number.

Checking for even and odd numbers using %

numbers = [1, 2, 3, 4, 5]
for num in numbers:
if num % 2 == 0:
print(f"{num} is even")
else:
print(f"{num} is odd")--OUTPUT--1 is odd
2 is even
3 is odd
4 is even
5 is odd

This code iterates through a list, using the modulo operator to check for divisibility by two. The condition num % 2 == 0 is the key to the whole operation—it’s a straightforward way to determine if a number is even.

  • If the remainder is 0, the number is even.
  • Any other result, which in this case will always be 1, means the number is odd.

The if/else statement uses this binary outcome to correctly categorize each number. This simple check is a powerful technique you'll find in many different algorithms and serves as a foundation for building logic in Python.

Creating cyclic patterns with modulo

# Cycle through values 0, 1, 2 repeatedly
for i in range(10):
index = i % 3
print(f"Item {i} maps to position {index}")--OUTPUT--Item 0 maps to position 0
Item 1 maps to position 1
Item 2 maps to position 2
Item 3 maps to position 0
Item 4 maps to position 1
Item 5 maps to position 2
Item 6 maps to position 0
Item 7 maps to position 1
Item 8 maps to position 2
Item 9 maps to position 0

The modulo operator is perfect for creating repeating patterns. Here, the expression i % 3 constrains the result to a value between 0 and 2. As the loop counter i increases, the output cycles through these three numbers over and over again.

  • This technique is useful for assigning items to a fixed number of categories in a round-robin fashion.
  • Think of it for tasks like rotating through player turns in a game or applying a limited set of styles to a long list of items. These patterns are perfect for vibe coding applications.

Extracting digits from numbers with %

number = 7531
last_digit = number % 10
second_last = (number // 10) % 10
print(f"Last digit: {last_digit}")
print(f"Second last digit: {second_last}")--OUTPUT--Last digit: 1
Second last digit: 3

You can also use the modulo operator to pick digits out of a number. The expression number % 10 always isolates the last digit because it gives you the remainder after dividing by 10. This is one of the fundamental techniques for extracting digits from numbers.

  • To get the second to last digit, you first remove the last digit using integer division (// 10).
  • Then, you apply the same % 10 operation to the result. This combination effectively shifts your focus one digit to the left.

Advanced modulo techniques

With the fundamentals covered, you can now tackle more complex scenarios, such as working with negative numbers or using specialized functions like divmod() and pow().

Understanding modulo with negative numbers

print(-7 % 3) # Modulo with negative dividend
print(7 % -3) # Modulo with negative divisor
print(-7 % -3) # Both negative--OUTPUT--2
-2
-1

When you use the modulo operator with negative numbers, Python follows a simple rule: the sign of the result always matches the sign of the divisor—the second number. This behavior might differ from other languages you've used.

  • -7 % 3 yields 2 because the divisor 3 is positive.
  • 7 % -3 results in -2, matching the negative sign of the divisor -3.
  • Likewise, -7 % -3 gives -1, as the divisor is again negative.

Keeping this rule in mind ensures your calculations are predictable, especially in algorithms involving negative values.

Using the divmod() function

quotient, remainder = divmod(17, 5)
print(f"17 divided by 5: quotient = {quotient}, remainder = {remainder}")
result = divmod(11, 3)
print(f"Result type: {type(result)}, value: {result}")--OUTPUT--17 divided by 5: quotient = 3, remainder = 2
Result type: <class 'tuple'>, value: (3, 2)

The built-in divmod() function is a handy shortcut that performs both integer division and a modulo operation at the same time. It's more efficient than running the // and % operators separately because it does both calculations in one go.

  • The function returns a tuple containing two values: the quotient and the remainder.
  • In the example, divmod(17, 5) returns (3, 2), which is then unpacked into the quotient and remainder variables. This is a clean way to handle the output.

Efficient modular exponentiation with pow()

base = 4
exponent = 13
modulus = 497
result = pow(base, exponent, modulus)
print(f"{base}^{exponent} mod {modulus} = {result}")--OUTPUT--4^13 mod 497 = 445

The pow() function provides a highly efficient way to handle modular exponentiation. Instead of first calculating a massive number with base ** exponent and then finding the remainder, pow(base, exponent, modulus) does it all in one optimized step. This approach is much faster and memory-efficient, especially with large numbers.

  • It's a direct replacement for the less efficient (base ** exponent) % modulus.
  • The function avoids creating huge intermediate numbers, which keeps your code running smoothly.
  • You'll often see this technique used in cryptography, where large-number calculations are standard.

Move faster with Replit

Replit is an AI-powered development platform that comes with all Python dependencies pre-installed, so you can skip setup and start coding instantly. This allows you to move from learning individual techniques to building complete applications faster. With Agent 4, you can take an idea to a working product—it handles the code, databases, APIs, and deployment directly from a description.

Instead of just practicing with operators like %, you can build a complete product. For example:

  • A task scheduler that distributes jobs evenly across a set number of workers using round-robin logic.
  • A unit converter that transforms a large number of seconds into a more readable format of hours, minutes, and seconds.
  • A validation tool that checks if a user ID is valid by using its final digit as a checksum, calculated from the preceding digits.

Simply describe your app, and Replit will write the code, test it, and fix issues automatically, all within your browser.

Common errors and challenges

While powerful, the % operator comes with common challenges, including division by zero, floating-point inaccuracies, and off-by-one indexing errors.

Avoiding division by zero with the % operator

Just like with standard division, attempting a modulo operation with a zero divisor is impossible. Python will stop execution and raise a ZeroDivisionError. It's a critical edge case to handle when using the % operator with dynamic divisors. The following example demonstrates what happens.

divisors = [5, 0, 3]
for d in divisors:
result = 10 % d
print(f"10 % {d} = {result}")

The loop processes 10 % 5 successfully but crashes when it reaches the second item, 0. Since 10 % 0 is an undefined operation, Python raises an error. The following code demonstrates how to handle this safely.

divisors = [5, 0, 3]
for d in divisors:
if d == 0:
print(f"10 % {d} = Error: Cannot divide by zero")
else:
result = 10 % d
print(f"10 % {d} = {result}")

The corrected code adds a simple guard clause. An if d == 0: statement checks the divisor before the % operation runs, preventing the ZeroDivisionError by handling the problematic case separately. This makes your code more robust.

  • Keep an eye out for this error when divisors come from user input, external data, or any calculation that could result in zero.

Handling floating-point precision with the % operator

Using the % operator with floating-point numbers can be tricky. Computers often store decimals with tiny inaccuracies, which can lead to unexpected remainders where you'd expect zero. The following example highlights how this subtle precision issue can break your logic.

a = 0.1 + 0.2 # Should be equal to 0.3
print(f"{a} % 0.3 = {a % 0.3}")
print("Is a divisible by 0.3?", a % 0.3 == 0)

The expression 0.1 + 0.2 results in a number slightly different from 0.3 due to floating-point math. This causes a % 0.3 to leave a tiny, unexpected remainder, so the check for divisibility fails. The following code demonstrates a reliable way to handle this.

a = 0.1 + 0.2 # Approximately 0.3
print(f"{a} % 0.3 = {a % 0.3}")
print("Is a divisible by 0.3?", abs(a % 0.3) < 1e-10)

The corrected code works around this by not checking for an exact zero. Instead of a % 0.3 == 0, it checks if the remainder is close enough to zero to be considered negligible. The expression abs(a % 0.3) < 1e-10 uses a small tolerance to account for floating-point inaccuracies, ensuring your divisibility checks are reliable.

  • This approach is crucial for financial calculations or scientific data where decimal precision matters.

Fixing off-by-one errors when using % for indexing

Off-by-one errors are a classic pitfall when using the % operator for list indexing. This usually happens when your counting starts at one, but the list indices start at zero, causing a mismatch. The following code demonstrates this common issue.

weekdays = ["Mon", "Tue", "Wed", "Thu", "Fri"]
day_number = 8 # Should wrap to "Wed"
index = day_number % 5
print(f"Day {day_number} is {weekdays[index]}")

The calculation day_number % 5 results in an index of 3, incorrectly mapping the eighth day to Thursday. This mismatch occurs because the logic doesn't account for Python's zero-based list indexing. The corrected code demonstrates the proper approach.

weekdays = ["Mon", "Tue", "Wed", "Thu", "Fri"]
day_number = 8 # Should wrap to "Wed"
index = (day_number - 1) % 5
print(f"Day {day_number} is {weekdays[index]}")

The corrected code aligns the one-based day count with Python's zero-based list indices by subtracting one from the day number. The expression (day_number - 1) % 5 ensures that day 8 correctly maps to index 2, which is "Wed".

  • This kind of error is common when your input data, like dates or numbered lists, doesn't naturally start from zero.

Real-world applications

Moving beyond the challenges, the % operator is a key tool for solving practical problems like time conversion and calendar logic.

Converting seconds to hours, minutes and seconds with %

You can use the % operator alongside integer division to elegantly convert a large number of seconds into a familiar hours, minutes, and seconds format.

total_seconds = 3665
hours = total_seconds // 3600
minutes = (total_seconds % 3600) // 60
seconds = total_seconds % 60
print(f"{total_seconds} seconds = {hours}h {minutes}m {seconds}s")
print(f"Digital clock format: {hours:02d}:{minutes:02d}:{seconds:02d}")

This snippet demonstrates a practical way to convert seconds into a familiar time format using a combination of integer division (//) and modulo (%). The process works by progressively calculating each time unit and removing it from the total.

  • First, total_seconds // 3600 isolates the number of full hours.
  • Then, (total_seconds % 3600) // 60 takes the leftover seconds and finds how many full minutes are in them.
  • Finally, total_seconds % 60 calculates the remaining seconds that don't fit into a full minute.

Day of the week calculation with %

The % operator is also great for calendar-related logic, where it can determine the day of the week by wrapping around a seven-day cycle.

def get_day_of_week(day_number):
days = ["Monday", "Tuesday", "Wednesday", "Thursday",
"Friday", "Saturday", "Sunday"]
return days[day_number % 7]

today = 0 # Monday
print(f"Today (day {today}): {get_day_of_week(today)}")
print(f"10 days later: {get_day_of_week(today + 10)}")
print(f"100 days later: {get_day_of_week(today + 100)}")

The get_day_of_week function uses the modulo operator (%) to map any number of days to a specific day of the week. The expression day_number % 7 is the core of this logic, as it guarantees the result is always a valid list index from 0 to 6.

  • This works by taking the remainder of a division by 7, effectively constraining the output to the seven items in the days list.
  • It’s how the function correctly calculates that 10 days from the starting point (day 0) lands on a Thursday (index 3).

Get started with Replit

Put your knowledge of the % operator into practice. Give Replit Agent a prompt like, “Build a time converter for HH:MM:SS format,” or “Create a round-robin task scheduler for a list of workers.”

Replit Agent writes the code, tests for errors, and deploys your app from a simple description. Start building with Replit.

Build your first app today

Describe what you want to build, and Replit Agent writes the code, handles the infrastructure, and ships it live. Go from idea to real product, all in your browser.

Build your first app today

Describe what you want to build, and Replit Agent writes the code, handles the infrastructure, and ships it live. Go from idea to real product, all in your browser.