C and Python - different behaviour of the modulo (%) operation
- Both variants are correct, however in mathematics (number theory in particular), Python's modulo is most commonly used.
- In C, you do
((n % M) + M) % M
to get the same result as in Python. E. g.((-1 % 10) + 10) % 10
. Note, how it still works for positive integers:((17 % 10) + 10) % 10 == 17 % 10
, as well as for both variants of C implementations (positive or negative remainder).
The modulo operation on negative numbers in Python
Unlike C or C++, Python's modulo operator (%
) always return a number having the same sign as the denominator (divisor). Your expression yields 3 because
(-5) / 4 = -1.25 --> floor(-1.25) = -2
(-5) % 4 = (-2 × 4 + 3) % 4 = 3.
It is chosen over the C behavior because a nonnegative result is often more useful. An example is to compute week days. If today is Tuesday (day #2), what is the week day N days before? In Python we can compute with
return (2 - N) % 7
but in C, if N ≥ 3, we get a negative number which is an invalid number, and we need to manually fix it up by adding 7:
int result = (2 - N) % 7;
return result < 0 ? result + 7 : result;
(See http://en.wikipedia.org/wiki/Modulo_operator for how the sign of result is determined for different languages.)
Why is the behavior of the modulo operator (%) different between C and Ruby for negative integers?
Wiki says:
Given two positive numbers,
a
(the dividend) andn
(the divisor), a modulo n (abbreviated as a mod n) is the remainder of the Euclidean division ofa by n
.
.... When eithera
orn
is negative, the naive definition breaks down and programming languages differ in how these values are defined.
Now the question is why -40 % 3
is 2
in Ruby or in other words what is the mathematics behind it ?
Let's start with Euclidean division which states that:
Given two integers
a
andn
, withn ≠ 0
, there exist unique integersq
andr
such thata = n*q + r
and0 ≤ r < |n|
, where|n|
denotes the absolute value ofn
.
Now note the two definitions of quotient:
- Donald Knuth described floored division where the quotient is defined by the floor function
q=floor(a/n)
and the remainderr
is:
Here the quotient (q
) is always rounded downwards (even if it is already negative) and the remainder (r
) has the same sign as the divisor.
- Some implementation define quotient as:
q = sgn(a)floor(|a| / n)
whre sgn
is signum function.
and the remainder (r
) has the same sign as the dividend(a
).
Now everything depends on q
:
- If implementation goes with definition
1
and defineq
asfloor(a/n)
then the value of40 % 3
is1
and-40 % 3
is2
. Which here seems the case for Ruby.- If implementation goes with definition
2
and defineq
assgn(a)floor(|a| / n)
, then the value of40 % 3
is1
and-40 % 3
is-1
. Which here seems the case for C and Java.
Python-style integer division & modulus in C
The direction for rounding with signed integer division is not specified in older C standards. However, in C99 it is specified to round towards zero.
Here's portable code which works with all versions of the C standards and CPU architectures:
int py_div(int a, int b)
{
if (a < 0)
if (b < 0)
return -a / -b;
else
return -(-a / b) - (-a % b != 0 ? 1 : 0);
else if (b < 0)
return -(a / -b) - (a % -b != 0 ? 1 : 0);
else
return a / b;
}
int py_mod(int a, int b)
{
if (a < 0)
if (b < 0)
return -(-a % -b);
else
return -a % b - (-a % -b != 0 ? 1 : 0);
else if (b < 0)
return -(a % -b) + (-a % -b != 0 ? 1 : 0);
else
return a % b;
}
I did some superficial tests and it appears to give the same results as Python. This code may not be maximally efficient, but a good C compiler can probably optimize it adequately, especially if you put the code in a header as static functions.
You may also want to take a look at this closely related question: Integer division rounding with negatives in C++.
regarding behaviour of modulo operation?
When we divider (a/b)%MOD , then we do something like this .
(a/b)%MOD
(a*inverse(b))%MOD // You have to find the inverse of b. To find the inverse of b use Fermat Theorem.
Note never divide a/b and then take MOD , first find the inverse of b and then do a*b and then MOD it .
Why -1%26 = -1 in Java and C, and why it is 25 in Python?
Python's %-operator calculates the mathematical remainder, not the modulus. The remainder is by definition a number between 0 and the divisor, it doesn't depend on the sign of the dividend like the modulus.
modulo of a number - python vs c#
The premise of the question is incorrect. The %
operator in C# is not the modulus operator, it is the remainder operator, while in Python it is a modulus operator.
As Eric Lippert Describes, modulus and remainder are the same for all positive numbers, but they handle negative numbers differently.
Despite both C# and Python having a %
operator, doesn't mean they both represent a modulus.
It's worth noting that other languages, such as C++ and Java use remainder for the %
operator, not modulus, which likely contributed to why C# choose to use remainder as well. Since there isn't a lot of consistency in what is meant by the %
operator, I would suggest looking it up in the language docs whenever working with a new language.
C Modulo operation differences with negative dividend and divisor is long unsigned
C99 section 6.5.5/6 requires that when a/b is representable:
(a/b) * b + a%b shall equal a
And from 6.5.5/3
The usual arithmetic conversions are performed on the operands.
For more details about arithmetic conversion, please check section 6.3.1.8.
Now it seems on your implementation sizeof(long) = sizeof(long long) = 64 bits
For the first 4 cases, signed or unsigned divisor can be changed to type of numerator (i.e. long long int
), but in last 2 cases dividend must be changed(casted or reinterpreted as) to unsigned type as divisor has same width and is unsigned causing the result.
On some systems where sizeof(long) < sizoef(long long)
, second last result should be different.
Related Topics
What Happens When a Module Is Imported Twice
How to Add an Integer to Each Element in a List
Pandas Split Column into Multiple Columns by Comma
Python Os.Path.Join on Windows
Ssl.Sslerror: Tlsv1 Alert Protocol Version
Redirecting Stdout and Stderr to a Pyqt4 Qtextedit from a Secondary Thread
Want to Find Contours -> Valueerror: Not Enough Values to Unpack (Expected 3, Got 2), This Appears
Get Fully Qualified Class Name of an Object in Python
Is It Safe to Replace a Self Object by Another Object of the Same Type in a Method
How to Clamp an Integer to Some Range
Replicating Rows in a Pandas Data Frame by a Column Value
How to Make a Selenium Script Undetectable Using Geckodriver and Firefox Through Python
Function Changes List Values and Not Variable Values in Python
Pip Cannot Uninstall <Package>: "It Is a Distutils Installed Project"