Вопрос по c#, math – % (мод) объяснение

30

Сегодня я писал программу на C #, и я использовал% вычислить некоторый индекс ... Моя программа не работает, поэтому я отладил ее и понял, что & quot;%& Quot; не работает, как на других языках программирования, которые я знаю.

Например:

В питоне% возвращает значения как это:

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

В 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

Я сделал что-то не так или% не работает как надо?

В языках, производных от C,% не является оператором модуля. Этоremainder оператор.Eric Lippert explains. Raymond Chen
Как я могу использовать оператор модуля в C #? Wolfy
@RaymondChen это похоже на ответ, а не комментарий. Я могу объявить это, если хотите. Mr Lister
@Wolfyc = a % b; if (c < 0) { c += b; } return c; Aaron Franke
Wolfy - просто добавьте 5, если значение отрицательное. Cheeso

Ваш Ответ

4   ответа
6

Оба ответа верны. Хотя лично я считаю, что «всегда позитивно» один имеет больше смысла.

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

int mod(int a, int n) {
    return ((a%n)+n) % n;
}
Я обнаружил, что более эффективно написать это так:int c = a % b; if (c < 0) { c += b; } return c; хотя следует отметить, что он не учитывает отрицательные делители
@EricLippert Теоретически он должен возвращать значение между 0 и вторым аргументом (поэтому, если делитель отрицательный, то он должен быть отрицательным и положительным, когда делитель положительный, независимо от знака дивиденда), но отрицательные делители очень редки.
что значитmod(-5, 2) вернуть?
mod(-2, -5) возвращает -2. Вы сказали, что он должен возвращать всегда положительные значения, но есть входные данные, которые заставляют его возвращать отрицательные значения. Это приемлемо? Это ожидается?
Черт ... Хорошо, позвольте мне попробовать еще раз.
14

различное поведение является дизайном. Разные языки просто приписывают разные значения% оператор.

Ты спрашиваешь:

How can I use modulus operator in C#?

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

int mod(int a, int n)
{
    int result = a % n;
    if ((result<0 && n>0) || (result>0 && n<0)) {
        result += n;
    }
    return result;
}
Ваш код дает неверные результаты, например, mod (-5, 5) == 5. Рабочий пример, см.answer
@Drake @DavidHeffernan Я исправил ошибку в коде этого ответа. Проблема заключалась в том, что он должен проверитьresultзначение не дляaзначение.
1
Это полезная ссылка, но она далека от полного ответа.
5

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

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

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.

Таким образом, оба результата, Python и C #, верны! Числаthe same по модулю5 арифметика вы выбрали. Это также было быmathematically правильно вернуть (5, 6, 7, 8, 9) например. Просто немного странно.

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

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?"

& # X2014;What's the difference? Remainder vs Modulus by Eric Lippert

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

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

Тестовая реализация:

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
Что такое «канонический модуль»? -2 и -5? Ваша программа дает -2, но я думаю, что вы намеревались дать неотрицательные результаты. Хочешь попробовать еще раз?
@EricLippert Это не так. Возвращает 3 и 0 соответственно. Смотрите мое редактирование.
Уверяю вас, ваш фрагмент говорит, что канонический модуль -2 и -5 равен -2. Попытайся:class P { static void Main() { int n = -2, m = -5; System.Console.WriteLine(((n%m)+m)%m)); } } Запустите его, и вы получите -2 в распечатанном виде. Если вы хотели, чтобы канонический модуль был неотрицательным, вы не достигли своего намерения. Хочешь попробовать еще раз?
@Eric Ах, Гоча! -5 был по модулю, а не по другому входу ... Хорошо, это все еще согласуется с питоном, хотя:python -c 'print -2%-5;' возвращается-2, Это то, чего ожидал ОП, я думаю.
Для версии, которая правильно обрабатывает отрицательные делители, см. Этот ответstackoverflow.com/a/10065670/4441547 Это, вероятно, довольно редко, хотя для большинства случаев использования ответ выше работает нормально.

Похожие вопросы