Programming

Modulo in Python, JavaScript and C: A Language Comparison

The % operator behaves differently across languages. Compare modulo in Python, JavaScript, C, Java and more, with a behaviour table, negative-number results and portable code patterns.

By Remainder Calculator Team

The modulo operator returns the remainder of a division, but its result for negative numbers changes from language to language. Python’s -7 % 3 returns 2, while JavaScript and C return −1 for the same expression, because Python uses floored division and C-family languages use truncated division. Positive numbers agree everywhere, so 17 % 5 returns 2 in every language. The Remainder Calculator shows the mathematical result, and this guide maps how each language differs so code stays correct when it moves between them.

Why track this per language? Three payoffs. You stop chasing off-by-one bugs when wrapping negative indices, ported code keeps producing the output it did before, and cross-language math libraries become safe to trust. The gaps only surface with negative operands, and they all trace back to one design choice about how the quotient gets rounded.

Every modulo expression breaks into the same 3 parts: a dividend, the operator, and a divisor. What follows walks through the two definitions behind the split, a behaviour table spanning 8 languages, the negative-number cases that trip people up, and portable patterns that return one answer everywhere.

Why the % Operator Differs Between Languages

The % operator differs because languages disagree on how to round the quotient before finding the remainder. Two definitions exist, and each produces a different sign for negative inputs.

  • Truncated division rounds the quotient toward zero. The remainder takes the sign of the dividend. C, C++, Java, JavaScript, Go, Rust, C# and Swift use this rule.
  • Floored division rounds the quotient toward negative infinity. The remainder takes the sign of the divisor. Python and Ruby use this rule.

Both satisfy the identity dividend = divisor × quotient + remainder, the same rule behind how to find the remainder by hand, so both are mathematically valid. The truncated versus floored division split is the single reason the operators disagree, and it only ever shows when one operand is negative. The core operation stays the same in every language, as covered in the modulo operator explained; only the sign of the result moves.

Modulo Behaviour Across Languages

The table below lists the result of 4 expressions in 8 languages. Positive inputs match everywhere; the negative rows expose the split.

Language17 % 5-7 % 37 % -3Definition
Python22−2Floored
Ruby22−2Floored
JavaScript2−11Truncated
C2−11Truncated
C++2−11Truncated
Java2−11Truncated
Go2−11Truncated
Rust2−11Truncated

Two patterns explain every cell. Under floored division the result matches the sign of the divisor, so -7 % 3 is positive and 7 % -3 is negative. Under truncated division the result matches the sign of the dividend, so -7 % 3 is negative and 7 % -3 is positive.

Modulo in Python

Python uses floored division, so its modulo result always takes the sign of the divisor. -7 % 3 returns 2, and 7 % -3 returns −2.

Python computes -7 % 3 in 3 steps:

  1. Divide and floor: floor(−7 / 3) = floor(−2.33) = −3.
  2. Multiply: 3 × (−3) = −9.
  3. Subtract: −7 − (−9) = 2.

Need both the quotient and the modulo at once? divmod(-7, 3) hands back the tuple (-3, 2) in a single call. When you want the truncated result that matches C instead, math.fmod(-7, 3) returns −1.0. That floored default is why Python is handy for cyclic indexing: a negative index wraps to a valid positive position without any extra code.

Modulo in JavaScript

JavaScript rounds its quotient toward zero, which is truncated division, so its % result takes the sign of the dividend. -7 % 3 returns −1, and 7 % -3 returns 1.

JavaScript computes -7 % 3 in 3 steps:

  1. Divide and truncate: trunc(−7 / 3) = trunc(−2.33) = −2.
  2. Multiply: 3 × (−2) = −6.
  3. Subtract: −7 − (−6) = −1.

One thing C won’t do: the JavaScript % operator also works on floating-point numbers, so 5.5 % 2 returns 1.5. Watch out for negative array indices, though. -1 % length returns a negative value that isn’t a valid position, so it needs correcting first.

Modulo in C and C++

C and C++ follow truncated division, matching JavaScript exactly. -7 % 3 returns −1, and 7 % -3 returns 1. The C99 standard nailed down the rounding direction toward zero, so this behaviour has been guaranteed ever since.

Here the % operator works only on integers. For floating-point remainders you reach for the fmod() function from math.h, so fmod(7.5, 2.0) returns 1.5. Java and Go inherit the same truncated rule, which is why one portable helper covers the entire C family. The same truncated result appears in modulo of negative numbers, where each sign case is traced in full.

A Portable Modulo That Matches Everywhere

A non-negative modulo that behaves the same in every language uses the expression ((a % b) + b) % b. This pattern converts a truncated result into the floored one, so it always returns a value between 0 and b − 1.

The expression fixes -7 % 3 in a truncating language:

  1. Inner modulo: -7 % 3 = −1.
  2. Add the divisor: −1 + 3 = 2.
  3. Outer modulo: 2 % 3 = 2.

The result is 2, matching Python. Reach for this helper whenever an index, hour, or hash has to stay non-negative no matter the input sign. Wrap a decrementing counter with it and a carousel or ring buffer stays inside bounds, one practical modulo use case that sits alongside primality testing.

Language Reference Table

LanguageInteger moduloFloat moduloNon-negative helper
Pythona % bmath.fmod(a, b)a % b (already floored)
JavaScripta % ba % b((a % b) + b) % b
Ca % bfmod(a, b)((a % b) + b) % b
Javaa % ba % bMath.floorMod(a, b)
Goa % bmath.Mod(a, b)((a % b) + b) % b
Rusta % ba % ba.rem_euclid(b)

Java ships Math.floorMod(a, b) and Rust ships a.rem_euclid(b), both returning the floored result directly. Choosing a built-in over the manual helper makes the intent clear and avoids the double operation.

Common Cross-Language Mistakes

Four errors appear when modulo code moves between languages:

  • Porting Python index math to JavaScript without adding the ((a % b) + b) % b guard.
  • Using % on floats in C, where the operator is integer-only and needs fmod().
  • Assuming -7 % 3 returns the same sign in Python and Java, when Python gives 2 and Java gives −1.
  • Comparing a modulo result to 0 for divisibility, which stays correct in every language and is the one case that never breaks.

The divisibility test a % b == 0 is portable, because a zero remainder has no sign to disagree about, and it mirrors the hand divisibility rules for each divisor. Every other negative case needs the language checked first. To trace where any of these results come from, work the division out with the full long division method or apply faster mental shortcuts for common divisors.

Frequently Asked Questions

Why does Python give a different modulo than JavaScript?

Python gives a different modulo because it uses floored division while JavaScript uses truncated division. Python’s -7 % 3 returns 2, taking the divisor’s sign, and JavaScript’s returns −1, taking the dividend’s sign.

Does modulo work the same for positive numbers in all languages?

Yes, modulo returns the same result for positive numbers in every language. 17 % 5 returns 2 in Python, JavaScript, C, Java and Go without exception.

How do I get a non-negative modulo in JavaScript or C?

Use the expression ((a % b) + b) % b to get a non-negative modulo. It converts the truncated result into a value between 0 and one less than the divisor.

Can I use % on decimal numbers?

The % operator works on decimals in Python, JavaScript, Java and Rust, but not in C or C++. C requires the fmod() function from math.h for floating-point remainders.

Conclusion

For positive numbers, every language lands on the same answer. Negative numbers are where they part ways. Python and Ruby floor the quotient, so their result follows the divisor’s sign; JavaScript, C, C++, Java, Go and Rust truncate it, so their result follows the dividend’s sign. Two rules cover the whole table.

Once you know which rule a language follows, the off-by-one bugs fade, ported code returns identical output, and cross-language math stops surprising you. One pattern gets you there: ((a % b) + b) % b, or a built-in like Math.floorMod and rem_euclid. Drop any dividend and divisor into the Remainder Calculator to check a modulo result against the language you’re working in.

← Back to Blog