49

Today I was writing a program in C#, and I used % to calculate some index... My program didn't work, so I debugged it and I realized that "%" is not working like in other program languages that I know.

For example:

In Python % returns values like this:

for x in xrange (-5, 6):
     print x, "% 5 =", x % 5

-5 % 5 = 0
-4 % 5 = 1
-3 % 5 = 2
-2 % 5 = 3
-1 % 5 = 4
0 % 5 = 0
1 % 5 = 1
2 % 5 = 2
3 % 5 = 3
4 % 5 = 4
5 % 5 = 0

In C#:

for (int i = -5; i < 6; i++)
{
    Console.WriteLine(i + " % 5 = " + i % 5);
}

-5 % 5 = 0
-4 % 5 = -4
-3 % 5 = -3
-2 % 5 = -2
-1 % 5 = -1
0 % 5 = 0
1 % 5 = 1
2 % 5 = 2
3 % 5 = 3
4 % 5 = 4
5 % 5 = 0

Did I do something wrong or is % not working like it should?

Ola Ström
  • 4,136
  • 5
  • 22
  • 41
Wolfy
  • 4,213
  • 8
  • 35
  • 42
  • 47
    In C-derived languages, % is not the modulus operator. It is the *remainder* operator. [Eric Lippert explains](http://blogs.msdn.com/b/ericlippert/archive/2011/12/05/what-s-the-difference-remainder-vs-modulus.aspx). – Raymond Chen Apr 08 '12 at 18:08
  • 8
    @RaymondChen that looks like an answer, not a comment. I can upvote it if you want, though. – Mr Lister Apr 08 '12 at 18:14
  • 1
    How can I use modulus operator in C#? – Wolfy Apr 08 '12 at 19:14
  • 3
    Wolfy - just add 5 if the value is negative. – Cheeso Apr 08 '12 at 19:26
  • @Wolfy `c = a % b; if (c < 0) { c += b; } return c;` – Aaron Franke Mar 25 '18 at 23:11
  • Painfully, Microsoft has blasted Lippert's blog post @RaymondChen mentions. Thankfully archive.org has many copies. [This is one](https://web.archive.org/web/20120211021512/http://blogs.msdn.com/b/ericlippert/archive/2011/12/05/what-s-the-difference-remainder-vs-modulus.aspx). **EDIT:** Actually it looks like they moved it [here](https://learn.microsoft.com/en-us/archive/blogs/ericlippert/whats-the-difference-remainder-vs-modulus) with no forward. /shrug – ruffin May 04 '21 at 13:34

3 Answers3

20

As explained in the comments, the different behaviour is by design. The different languages just ascribe different meanings to the % operator.

You ask:

How can I use modulus operator in C#?

You can define a modulus operator yourself that behaves the same way as the Python % operator:

int mod(int a, int n)
{
    int result = a % n;
    if ((result<0 && n>0) || (result>0 && n<0)) {
        result += n;
    }
    return result;
}
mjk
  • 2,443
  • 4
  • 33
  • 33
David Heffernan
  • 601,492
  • 42
  • 1,072
  • 1,490
  • 9
    Your code gives incorrect results, for example mod(-5, 5) == 5. For a working example, see this [answer](http://stackoverflow.com/questions/1082917/mod-of-negative-number-is-melting-my-brain) – Drake Jul 20 '13 at 23:04
  • @Drake @DavidHeffernan I fixed the bug in this answer's code. The problem was that it should check for the `result`'s value, not for `a`'s value. – Aaron Franke Apr 11 '18 at 00:03
10

Both answers are correct. Although personally I think the "always positive" one makes more sense.

You can define your own modulus function that only gives positive answers like this:

int mod(int a, int n) {
    return ((a%n)+n) % n;
}
Niet the Dark Absol
  • 320,036
  • 81
  • 464
  • 592
  • 1
    what does `mod(-5, 2)` return? – David Heffernan Apr 08 '12 at 19:32
  • Damn... Okay, let me try again. – Niet the Dark Absol Apr 08 '12 at 19:49
  • 1
    `mod(-2, -5)` returns -2. You said that it should return always positive values, but there are inputs which cause it to return negative values. Is this acceptable? Is it expected? – Eric Lippert Apr 09 '12 at 17:04
  • 1
    I have found that it's more efficient to write it like this: `int c = a % b; if (c < 0) { c += b; } return c;` although note that it doesn't account for negative divisors – Aaron Franke Apr 03 '18 at 05:59
  • @EricLippert In theory it should return between 0 and the second argument (so if the divisor is negative then it should be negative, and positive when divisor is positive, regardless of dividend's sign) but negative divisors are very uncommon. – Aaron Franke Apr 11 '18 at 01:45
  • To account for negative divisors, see this answer https://stackoverflow.com/a/10065670/4441547 This is probably fairly uncommon though so for most use cases the above answer works fine. – Aaron Franke Oct 19 '18 at 03:37
7

In modular arithmetic, one defines classes of numbers based on the modulo. In other words, in modulo m arithmetic, a number n is equivalent (read: the same) to n + m, n - m, n + 2m, n - 2m, etc.

One defines m "baskets" and every number falls in one (and only one) of them.

Example: one can say "It's 4:30 pm" or one can say "It's 16:30". Both forms mean exactly the same time, but are different representations of it.

Thus both, the Python and C# results are correct! The numbers are the same in the modulo 5 arithmetic you chose. It would also have been mathematically correct to return (5, 6, 7, 8, 9) for example. Just a bit odd.

As for the choice of representation (in other words, the choice on how to represent negative numbers), that is just a case of different design choices between the two languages.

However, that is not at all what the % operator actually does in C#. The % operator is not the canonical modulus operator; it is the remainder operator. The A % B operator actually answer the question "If I divided A by B using integer arithmetic, what would the remainder be?"

What's the difference? Remainder vs Modulus by Eric Lippert


Quick snippet to get the canonical modulus:

return ((n % m) + m) % m;

Test implementation:

Mono/C#:

machine:~ user$ cat mod.cs
using System;

public class Program
{
    public static void Main (string[] args)
    {
        Console.WriteLine(Mod(-2, 5));
        Console.WriteLine(Mod(-5, 5));
        Console.WriteLine(Mod(-2, -5));
    }

    public static int Mod (int n, int m)
    {
        return ((n % m) + m) % m;
    }
}

machine:~ user$ mono mod.exe
3
0
-2

Python:

machine:~ user$ cat mod.py
print -2%5;
print -5%5;
print -2%-5;

machine:~ user$ python mod.py
3
0
-2
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Sklivvz
  • 30,601
  • 24
  • 116
  • 172
  • 1
    What is the "canonical modulus" of -2 and -5? Your program gives -2, but I think you were intending it to give non-negative results. Care to try again? – Eric Lippert Apr 09 '12 at 13:51
  • @EricLippert It does not. It returns 3 and 0, respectively. See my edit. – Sklivvz Apr 09 '12 at 16:53
  • 1
    I assure you, your snippet says that the canonical modulus of -2 and -5 is -2. Try it: `class P { static void Main() { int n = -2, m = -5; System.Console.WriteLine(((n%m)+m)%m)); } }` Run that, you'll get -2 printed out. If it was your intention that the canonical modulus be non-negative, you have failed to achieve your intention. Care to try again? – Eric Lippert Apr 09 '12 at 16:58
  • @Eric Ah, gotcha! -5 was the modulo and not another input... OK, that's still consistent with python, though: `python -c 'print -2%-5;'` returns `-2`. That's what the OP was expecting, I think. – Sklivvz Apr 09 '12 at 17:13
  • For a version that handles negative divisors correctly, see this answer https://stackoverflow.com/a/10065670/4441547 This is probably fairly uncommon though so for most use cases the above answer works fine. – Aaron Franke Oct 19 '18 at 03:39