Ready to practice?
Sign up to access interactive coding exercises and track your progress.
Modulo and Power Operations
Calculate remainders with the modulo operator and raise numbers to powers.
The remainder operator (operator%)
The remainder operator (sometimes called the modulo operator) returns what's left over after integer division. For instance, 13 / 3 = 4 with remainder 1, so 13 % 3 = 1. Similarly, 50 / 7 = 7 with remainder 1, so 50 % 7 = 1. This operator only works with integer types.
The remainder operator is particularly useful for checking if one number divides evenly into another. If a % b equals 0, then b divides evenly into a.
#include <iostream>
int main()
{
std::cout << "Enter a number: ";
int dividend{};
std::cin >> dividend;
std::cout << "Enter a divisor: ";
int divisor{};
std::cin >> divisor;
std::cout << "Remainder: " << dividend % divisor << '\n';
if ((dividend % divisor) == 0)
std::cout << dividend << " is evenly divisible by " << divisor << '\n';
else
std::cout << dividend << " is not evenly divisible by " << divisor << '\n';
return 0;
}
Sample runs:
Enter a number: 20
Enter a divisor: 5
Remainder: 0
20 is evenly divisible by 5
Enter a number: 20
Enter a divisor: 6
Remainder: 2
20 is not evenly divisible by 6
When the divisor is larger than the dividend, the result might seem unexpected at first:
Enter a number: 3
Enter a divisor: 10
Remainder: 3
3 is not evenly divisible by 10
This makes sense: 3 / 10 = 0 (integer division) with remainder 3. When the divisor exceeds the dividend, it "fits" zero times, leaving the entire dividend as the remainder.
Execution trace
Here's how 17 % 5 is calculated step-by-step:
| Step | Operation | Result |
|---|---|---|
| 1 | Divide: 17 / 5 | 3 (integer division truncates) |
| 2 | Multiply: 3 * 5 | 15 (how much 5 "used up") |
| 3 | Subtract: 17 - 15 | 2 (what's left over) |
So 17 % 5 = 2. The relationship is: dividend = (dividend / divisor) * divisor + (dividend % divisor).
The remainder operation answers: "If I have 17 items and pack them into groups of 5, how many items are left over?" This makes it perfect for tasks like determining if a number is even/odd, cycling through array indices, or formatting output every N items.
Remainder with negative numbers
The remainder operator handles negative operands. The sign of the result always matches the sign of the dividend (the left operand).
Enter a number: -20
Enter a divisor: 6
Remainder: -2
-20 is not evenly divisible by 6
Enter a number: 20
Enter a divisor: -6
Remainder: 2
20 is not evenly divisible by -6
Notice the remainder's sign matches the first operand in both cases.
Negative number edge cases
| Expression | Result | Why |
|---|---|---|
13 % 5 |
3 |
Both positive: 13 = 2*5 + 3 |
-13 % 5 |
-3 |
Negative dividend: sign matches -13 |
13 % -5 |
3 |
Negative divisor: sign matches 13 |
-13 % -5 |
-3 |
Negative dividend: sign matches -13 |
5 % 13 |
5 |
Divisor larger: nothing "fits" |
-5 % 13 |
-5 |
Sign matches -5 |
The sign of the remainder ALWAYS matches the sign of the dividend (the first operand). The sign of the divisor never affects the result's sign.
Nomenclature note: The C++ standard refers to this as the "remainder" operator. While commonly called "modulo," that term can be confusing because mathematical modulo differs from C++'s operator% when negative numbers are involved.
For example, mathematically:
-17 modulo 5 = 3-17 remainder 5 = -2
We prefer calling it the "remainder" operator for accuracy.
When the dividend might be negative, be careful with comparisons. You might write:
bool isOdd(int number)
{
return (number % 2) == 1; // fails for negative odd numbers
}
This fails for negative odd numbers like -7, because -7 % 2 equals -1, not 1.
Instead, compare against 0, which works correctly regardless of sign:
bool isOdd(int number)
{
return (number % 2) != 0; // works for positive and negative
}
When using the remainder operator, compare the result against `0` whenever possible to ensure correct behavior with negative numbers.
Where's the exponent operator?
You won't find an exponent operator in C++. The ^ symbol performs bitwise XOR, not exponentiation (covered in the Bit manipulation with bitwise operators and bit masks lesson).
For exponentiation, include the <cmath> header and use std::pow():
#include <cmath>
double result{std::pow(2.0, 8.0)}; // 2 to the 8th power = 256.0
Note that std::pow() uses double for parameters and return value. Floating-point calculations involve rounding errors, so results may not be perfectly precise even with whole numbers.
For integer exponentiation, you'll need a custom function. Here's an efficient implementation using the "exponentiation by squaring" algorithm:
#include <cassert>
#include <cstdint>
#include <iostream>
// note: exponent must be non-negative
// note: doesn't check for overflow—use with caution
constexpr std::int64_t powint(std::int64_t base, int exponent)
{
assert(exponent >= 0 && "powint: exponent must be non-negative");
if (base == 0)
return (exponent == 0) ? 1 : 0;
std::int64_t result{1};
while (exponent > 0)
{
if (exponent & 1) // if exponent is odd
result *= base;
exponent /= 2;
base *= base;
}
return result;
}
int main()
{
std::cout << powint(3, 10) << '\n'; // 3 to the 10th power
return 0;
}
This outputs:
59049
You don't need to understand the algorithm's internals to use the function.
Related content: We cover assertions in the Assert and static_assert lesson, and constexpr functions in the Constexpr functions lesson.
Advanced note: The constexpr keyword allows compile-time evaluation when used in constant expressions. Otherwise, the function executes normally at runtime.
Integer exponentiation almost always causes overflow for anything beyond small values. This is likely why the standard library doesn't include such a function.
Here's a safer version that detects overflow:
#include <cassert>
#include <cstdint>
#include <iostream>
#include <limits>
// Safer version that checks for overflow
// note: exponent must be non-negative
// Returns std::numeric_limits<std::int64_t>::max() if overflow occurs
constexpr std::int64_t powint_safe(std::int64_t base, int exponent)
{
assert(exponent >= 0 && "powint_safe: exponent must be non-negative");
if (base == 0)
return (exponent == 0) ? 1 : 0;
std::int64_t result{1};
bool negativeResult{false};
if (base < 0)
{
base = -base;
negativeResult = (exponent & 1);
}
while (exponent > 0)
{
if (exponent & 1)
{
if (result > std::numeric_limits<std::int64_t>::max() / base)
{
std::cerr << "powint_safe(): overflow detected\n";
return std::numeric_limits<std::int64_t>::max();
}
result *= base;
}
exponent /= 2;
if (exponent <= 0)
break;
if (base > std::numeric_limits<std::int64_t>::max() / base)
{
std::cerr << "powint_safe(): base overflow detected\n";
return std::numeric_limits<std::int64_t>::max();
}
base *= base;
}
if (negativeResult)
return -result;
return result;
}
int main()
{
std::cout << powint_safe(3, 10) << '\n'; // 3^10 = 59049
std::cout << powint_safe(30, 10) << '\n'; // overflow, returns max int64
return 0;
}
Summary
- Remainder operator (
%): Returns what's left over after integer division (e.g.,13 % 3 = 1); also called modulo operator - Checking divisibility: If
a % b == 0, thenbdivides evenly intoa - Sign behavior: The remainder's sign always matches the sign of the dividend (left operand)
- Terminology: C++ uses "remainder" (not "modulo") because mathematical modulo differs from
operator%when negative numbers are involved - Comparing remainder results: Always compare against
0when possible to ensure correct behavior with negative numbers (e.g.,number % 2 != 0instead ofnumber % 2 == 1) - No exponent operator: C++ doesn't have an exponentiation operator;
^performs bitwise XOR instead - std::pow(): Use
std::pow()from<cmath>for floating-point exponentiation (e.g.,std::pow(2.0, 8.0)) - Integer exponentiation: Requires a custom function; floating-point exponentiation may have rounding errors
- Overflow risk: Integer exponentiation causes overflow for all but small values; use overflow-checking implementations when needed
The remainder operator is essential for many common programming tasks like checking even/odd numbers or cycling through ranges. Understanding its sign behavior with negative numbers prevents subtle bugs. For exponentiation, use std::pow() for floating-point calculations, but be aware that you'll need custom implementations for integer exponentiation with overflow protection.
Modulo and Power Operations - Quiz
Test your understanding of the lesson.
Practice Exercises
Modulo and Power Operations
Use the modulo operator and std::pow for practical calculations like checking even/odd and calculating powers.
Lesson Discussion
Share your thoughts and questions
No comments yet. Be the first to share your thoughts!