45

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?

4

3 回答 3

18

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;
}
于 2012-04-08T19:19:30.267 回答
9

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;
}
于 2012-04-08T19:29:22.730 回答
6

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
于 2012-04-08T20:15:25.690 回答