Подтвердить что ты не робот

% (mod) объяснение

Сегодня я писал программу на С#, и я использовал % для вычисления некоторого индекса... Моя программа не работала, поэтому я отлаживал ее, и я понял, что "%" не работает, как на других языках программирования, которые я знаю.

Например:

В Python % возвращаются значения, подобные этому:

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

В С#:

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

Я сделал что-то неправильно или % не работает, как должен?

4b9b3361

Ответ 1

Как объяснено в комментариях, различное поведение является дизайном. Разные языки просто приписывают различные значения оператору %.

Вы спрашиваете:

Как я могу использовать оператор модуля в С#?

Вы можете определить оператор модуля самостоятельно, который ведет себя так же, как оператор Python %:

int mod(int a, int n)
{
    int result = a % n;
    if ((result<0 && n>0) || (result>0 && n<0)) {
        result += n;
    }
    return result;
}

Ответ 2

Оба ответа верны. Хотя лично я считаю, что "всегда положительный" имеет смысл.

Вы можете определить свою собственную функцию модуля, которая дает только такие положительные ответы:

int mod(int a, int n) {
    return ((a%n)+n) % n;
}

Ответ 3

В модульная арифметика, определяются классы чисел, основанные на модуле. Другими словами, в mod-m-арифметике число n равносильно (чит: то же) до n + m, n-m, n + 2m, n-2m и т.д.

Один определяет m "корзины", и каждое число попадает в один (и только один) из них.

Пример: можно сказать "Это 4:30 вечера", или можно сказать "Это 16:30". Обе формы означают ровно одно и то же время, но представляют собой разные представления.

Таким образом, результаты Python и С# верны! Числа одинаковы в выбранной по модулю 5 арифметике. Было бы также математически правильно возвращать (5, 6, 7, 8, 9), например. Немного странно.

Что касается выбора представления (другими словами, выбора того, как представлять отрицательные числа), это просто случай выбора дизайна между двумя языками.

Однако это совсем не то, что фактически делает оператор% в С#. Оператор% не является оператором канонического модуля; это оператор остатка. Оператор A% B фактически отвечает на вопрос "Если бы я разделил A на B с помощью целочисленной арифметики, каков был бы остаток?"

Какая разница? Остаток против Модуля Эриком Липпертом


Быстрый фрагмент, чтобы получить канонический модуль:

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

Реализация теста:

Mono/С#:

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

Ответ 5

Самый простой способ вычислить a mod b без какого-либо нового метода -

double aMODb = Math.Sign(a) * a % b;