How to use modulo in Python

A guide to Python's modulo operator. Learn different methods, see real-world applications, and get tips for debugging common errors.

How to use modulo in Python
Published on: 
Fri
Feb 13, 2026
Updated on: 
Tue
Feb 24, 2026
The Replit Team Logo Image
The Replit Team

The modulo operator, the % symbol in Python, is a powerful tool that finds the remainder of a division. It's essential for tasks that involve cyclical patterns and number theory.

Here, you'll explore key techniques and practical tips. You will also discover real-world applications and receive debugging advice to help you master the modulo operator in your own projects.

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

This example shows the % operator in action. First, it calculates 10 % 3, which results in a remainder of 1. This value is then stored in the remainder variable. The next two lines provide further examples of how the operator behaves.

  • 15 % 4 yields 3 because 4 goes into 15 three times, leaving a remainder of 3.
  • 8 % 2 results in 0. This is a classic way to check if a number is perfectly divisible or, in this case, even.

Common modulo applications

Beyond simply checking for even numbers, the % operator is your key to implementing cyclic behaviors, extracting individual digits, and solving other common programming puzzles.

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 demonstrates a fundamental use of the modulo operator. It checks each number's divisibility by 2 to sort them into even and odd categories. The core of this logic lies in the if num % 2 == 0 condition, which evaluates the remainder.

  • If the remainder is 0, the number is even because it divides perfectly by 2.
  • Otherwise, the remainder is 1, and the code classifies the number as odd.

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 sequences. By using i % 3, the code confines the output to a specific range. No matter how high the loop counter i gets, the result stored in index will always be 0, 1, or 2.

  • This operation creates a predictable cycle. As i increments, the index value repeats the sequence 0, 1, 2.
  • You can use this technique to rotate through a fixed number of items, like assigning users to groups or cycling through colors in a user interface.

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

The modulo operator is also a clever tool for deconstructing numbers. By calculating number % 10, you can easily isolate the last digit of any integer. This works because in our base-10 system, the remainder of a division by 10 is always the value in the ones place.

  • The code first gets the last digit with 7531 % 10, which yields 1.
  • To get the next digit, it combines integer division and modulo. First, number // 10 removes the last digit, resulting in 753. Then, 753 % 10 isolates the new last digit, 3.

Advanced modulo techniques

Beyond these everyday uses, the modulo operator also handles more complex situations involving negative numbers and can be optimized with 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's behavior can be surprising. The key rule is that the sign of the result always matches the sign of the divisor. This isn't universal; other programming languages might handle these calculations differently.

  • With -7 % 3, the divisor 3 is positive, so the result is 2.
  • Conversely, for 7 % -3, the divisor -3 is negative, making the result -2.
  • When both numbers are negative, as in -7 % -3, the negative divisor again dictates a negative result, which is -1.

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)

Python's built-in divmod() function offers a more efficient way to get both the quotient and remainder from a division. It combines the work of the integer division (//) and modulo (%) operators into a single, optimized call.

  • The function returns a single tuple containing two values: the quotient followed by the remainder. For instance, divmod(17, 5) produces (3, 2).
  • You can easily unpack this tuple into separate variables, like quotient, remainder, for cleaner and more direct code.

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 with three arguments provides a highly efficient way to perform modular exponentiation. It calculates (base ** exponent) % modulus all in one step. This is much faster than calculating base ** exponent first, as it avoids dealing with the potentially huge intermediate number.

  • The code pow(4, 13, 497) is a direct and optimized replacement for (4 ** 13) % 497.
  • This technique is crucial in fields like cryptography, where calculations often involve enormous numbers and performance is key.

Move faster with Replit

You can take these concepts from theory to production with Replit, an AI-powered development platform that transforms natural language into working applications. Describe what you want to build, and Replit Agent creates it—complete with databases, APIs, and deployment.

For the modulo techniques we've explored, Replit Agent can turn them into production-ready tools:

  • Build a task scheduler that uses the % operator to assign duties in a round-robin sequence.
  • Create a data validation utility that uses modulo arithmetic to verify checksums in product codes.
  • Deploy a content-rotation system that cycles through a list of featured items on a website.

Describe your app idea, and Replit Agent writes the code, tests it, and fixes issues automatically, all in your browser.

Common errors and challenges

The % operator is powerful, but you'll need to watch for common errors like division by zero, floating-point issues, and off-by-one bugs.

Avoiding division by zero with the % operator

Just like with standard division, attempting to use the modulo operator with a divisor of zero is a critical mistake. Python will raise a ZeroDivisionError, which halts your program immediately. This error occurs because division by zero is mathematically undefined. The following code demonstrates what happens when you try it.

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

The loop fails when it tries to calculate 10 % 0 during its second iteration, an invalid operation that raises a ZeroDivisionError. The corrected code below shows how to add a simple check to prevent this crash.

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 prevents the crash by adding a simple check. Before calculating the remainder, the if d == 0: condition verifies that the divisor isn't zero. This guardrail allows the program to handle the invalid operation gracefully instead of crashing.

  • You should always add this check when the divisor comes from user input or any external source where its value can't be guaranteed. This prevents unexpected ZeroDivisionError exceptions in your application.

Handling floating-point precision with the % operator

Using the % operator with floating-point numbers can be tricky. Computers can't always represent decimals perfectly, leading to small precision errors. These tiny inaccuracies can cause modulo calculations to return unexpected, non-zero remainders, breaking logic that expects an exact result.

The code below shows this in action, where a seemingly simple operation yields a surprising outcome.

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 calculation 0.1 + 0.2 results in a number slightly different from 0.3 due to floating-point imprecision. This tiny error means a % 0.3 isn't zero, causing the equality check to fail. The following code demonstrates a reliable fix.

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 avoids checking for exact equality with == 0, which is unreliable for floats. Instead, it checks if the remainder is "close enough" to zero to account for floating-point inaccuracies.

  • It calculates the absolute value of the remainder using abs().
  • It then compares this value against a small tolerance, like 1e-10.

This tolerance-based comparison is essential whenever you use the % operator with floating-point numbers that result from prior calculations.

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

Off-by-one errors are a common pitfall when using the % operator for array indexing, causing you to access the wrong element. This often happens when mixing one-based numbering with zero-based list indices. The following code shows this mistake in action.

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 8 % 5 yields an index of 3, incorrectly selecting "Thu" instead of "Wed". This off-by-one error occurs because the logic doesn't adjust for the list's zero-based indexing. The following code demonstrates the correct 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 subtracts 1 from day_number before applying the modulo operator. This simple adjustment synchronizes the one-based day count with Python's zero-based list indexing. Now, (8 - 1) % 5 correctly calculates an index of 2, pointing to "Wed".

  • Always watch for this potential error when you're mapping a numbered sequence, like days 1 through 7, to a zero-indexed data structure like a list or array.

Real-world applications

Beyond debugging, the % operator is essential for real-world tasks, from converting time units to calculating the day of the week.

Converting seconds to hours, minutes and seconds with %

By combining the modulo operator (%) with integer division (//), you can easily break down a large number of seconds into a standard 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 code converts a large number of seconds into a familiar hours, minutes, and seconds format. The logic systematically carves out each unit of time, making the total easily understandable.

  • First, total_seconds // 3600 calculates the number of full hours.
  • Next, (total_seconds % 3600) // 60 finds the remaining minutes after the hours are removed.
  • Finally, total_seconds % 60 isolates the final seconds that don't make up a full minute.

This step-by-step reduction ensures each part of the time is calculated correctly from the original total.

Day of the week calculation with %

The % operator makes it easy to calculate the day of the week by treating the seven days as a repeating 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 a number to a specific day. By calculating day_number % 7, it ensures the result is always an index between 0 and 6, which aligns perfectly with the seven-item days list.

  • With Monday set as day 0, the code finds the day of the week 10 days later. The operation 10 % 7 yields an index of 3, which corresponds to "Thursday".
  • Similarly, for 100 days later, 100 % 7 results in an index of 2, correctly identifying the day as "Wednesday".

Get started with Replit

Turn your knowledge into a real tool with Replit Agent. Describe what you want to build, like "a time converter that turns seconds into an HH:MM:SS format" or "a task scheduler that cycles through team members."

The agent writes the code, tests for errors, and deploys your app from a single prompt. Start building with Replit.

Get started free

Create and deploy websites, automations, internal tools, data pipelines and more in any programming language without setup, downloads or extra tools. All in a single cloud workspace with AI built in.

Get started for free

Create & deploy websites, automations, internal tools, data pipelines and more in any programming language without setup, downloads or extra tools. All in a single cloud workspace with AI built in.