Как я могу вычислить деление и по модулю для целых чисел в C #?

86

Как я могу рассчитать деление и по модулю для целых чисел в C #?

картал
источник
15
Это может быть слишком простым, но это реальный вопрос ...
2
Связанный пост и блог о том, почему %оператор не является оператором модуля в C #, необходимо прочитать .
RBT

Ответы:

123

Прежде чем задавать подобные вопросы, проверьте документацию MSDN .

Когда вы делите два целых числа, результат всегда целое. Например, результат 7/3 равен 2. Чтобы определить остаток от 7/3, используйте оператор остатка ( % ).

int a = 5;
int b = 3;

int div = a / b; //quotient is 1
int mod = a % b; //remainder is 2
as-cii
источник
9
% возвращает остаток, а не модуль (как вы указываете). Это не одно и то же, и они могут вызвать проблемы при работе с необычными случаями (например, с отрицательными индексами). Однако его можно использовать как оператор модуля, когда вы просто ищете, например, каждую 10-ю итерацию слабо положительного индексатора. Возможно, вы могли бы объяснить, как рассчитать реальный модуль упругости?
Cor_Blimey
1
Правда, я читал подобные посты, и у меня были проблемы с приложением :)
апокалипсис
1
... В чем именно смысл декларирования aи bесли вы не собираетесь их использовать? : D
leviathanbadger
1
Возможно, пользователь искал (как и я) функцию DivRem, поэтому вопрос может быть не таким тривиальным, как кажется на первый взгляд. Спасибо @danodonovan
Tancredi
1
Ответ не так прост, как утверждается в этом ответе, как также указывали другие, и может привести к трудным для отладки ошибкам. См. Https://stackoverflow.com/questions/10065080/mod-explanation
SansWit
88

А также есть Math.DivRem

quotient = Math.DivRem(dividend, divisor, out remainder);
данодонован
источник
2
На мой взгляд, это должен быть правильный ответ, потому что он обеспечивает частное И остаток в одной функции. Я не уверен, какой подход работает лучше (используя «a / b» для получения частного, а затем «a% b» для получения остатка или Math.DivRem), но этот подход, безусловно, намного приятнее читать (в моем случае мне нужно чтобы знать как частное, так и остаток) - спасибо!
Игорь
2
@ Игорь спасибо, когда был дан ответ на исходный вопрос, этой функции не существовало! Однако из-за существования функции замечание as-cii о проверке документации выглядит немного глупо .... :)
данодонован
5
Во избежание путаницы Math.DivRemне вычисляет div и mod за одну операцию. Это просто вспомогательная функция и ее исходный код именно: public static int DivRem(int a, int b, out int result) { result = a%b; return a/b; }.
NightElfik
9
@NightElfik Реализация может измениться в будущем, и для среды выполнения легче идентифицировать вызов метода для оптимизации, чем divrem
разделение
6
@kbolino Это отличный прогноз, так как она была изменена , по крайней мере , в .NET Ядра, делить и вычитать. И есть дополнительные оптимизации , запланированные в RyuJIT использовать одну команду x86 Див, хотя по общему признанию , изменения JIT также должны обнаружить %и /оператор , если они используются по отдельности.
Боб
15

Интересный факт!

Операция "модуля" определяется как:

a % n ==> a - (a/n) * n

Ссылка: Модульная арифметика

Таким образом, вы можете использовать свой собственный, хотя он будет намного медленнее, чем встроенный оператор%:

public static int Mod(int a, int n)
{
    return a - (int)((double)a / n) * n;
}

Изменить: вау, изначально здесь довольно плохо оговорились, спасибо @joren за то, что поймал меня

Теперь я полагаюсь на тот факт, что деление + приведение к целому в C # эквивалентно Math.Floor(т. Е. Отбрасывает дробь), но «истинная» реализация вместо этого будет выглядеть примерно так:

public static int Mod(int a, int n)
{
    return a - (int)Math.Floor((double)a / n) * n;
}

Фактически, вы можете увидеть разницу между% и «истинным модулем» следующим образом:

var modTest =
    from a in Enumerable.Range(-3, 6)
    from b in Enumerable.Range(-3, 6)
    where b != 0
    let op = (a % b)
    let mod = Mod(a,b)
    let areSame = op == mod
    select new 
    { 
        A = a,
        B = b,
        Operator = op, 
        Mod = mod, 
        Same = areSame
    };
Console.WriteLine("A      B     A%B   Mod(A,B)   Equal?");
Console.WriteLine("-----------------------------------");
foreach (var result in modTest)
{
    Console.WriteLine(
        "{0,-3} | {1,-3} | {2,-5} | {3,-10} | {4,-6}", 
        result.A,
        result.B,
        result.Operator, 
        result.Mod, 
        result.Same);
}

Полученные результаты:

A      B     A%B   Mod(A,B)   Equal?
-----------------------------------
-3  | -3  | 0     | 0          | True  
-3  | -2  | -1    | -1         | True  
-3  | -1  | 0     | 0          | True  
-3  | 1   | 0     | 0          | True  
-3  | 2   | -1    | 1          | False 
-2  | -3  | -2    | -2         | True  
-2  | -2  | 0     | 0          | True  
-2  | -1  | 0     | 0          | True  
-2  | 1   | 0     | 0          | True  
-2  | 2   | 0     | 0          | True  
-1  | -3  | -1    | -1         | True  
-1  | -2  | -1    | -1         | True  
-1  | -1  | 0     | 0          | True  
-1  | 1   | 0     | 0          | True  
-1  | 2   | -1    | 1          | False 
0   | -3  | 0     | 0          | True  
0   | -2  | 0     | 0          | True  
0   | -1  | 0     | 0          | True  
0   | 1   | 0     | 0          | True  
0   | 2   | 0     | 0          | True  
1   | -3  | 1     | -2         | False 
1   | -2  | 1     | -1         | False 
1   | -1  | 0     | 0          | True  
1   | 1   | 0     | 0          | True  
1   | 2   | 1     | 1          | True  
2   | -3  | 2     | -1         | False 
2   | -2  | 0     | 0          | True  
2   | -1  | 0     | 0          | True  
2   | 1   | 0     | 0          | True  
2   | 2   | 0     | 0          | True  
JerKimball
источник
«Теперь я полагаюсь на тот факт, что целочисленное деление в C # эквивалентно Math.Floor (то есть отбрасывает дробь)» - Но это не так. Целочисленное деление округляется до нуля, Math.Floor округляется до отрицательной бесконечности.
Joren
@Joren Извините, но нет - попробуйте запустить это: Enumerable.Range(0, 10).Select(x => (double)x / 10.0).Select(x => (int)x).ToList().ForEach(x => Console.WriteLine(x));- все 0
JerKimball
2
Во-первых, я говорю о целочисленном делении . Что произойдет, если вы выполните деление с плавающей запятой, а затем приведете к целому числу, не имеет значения (даже если это дает тот же результат). Во-вторых, я не уверен, почему вы ожидаете, что целые числа от 0 до 9 будут давать что-либо, кроме 0, после деления на 10 и усечения до целой части. Если в результате 1 , которые будут округлять в сторону от нуля или по направлению к положительной бесконечности. В-третьих, нет никакой разницы между округлением в сторону нуля и в сторону отрицательной бесконечности для положительных чисел, так что вы даже не решаете проблему.
Joren
Math.Floor(-10.0 / 3.0)и -10 / 3это не одно и то же.
Joren
@joren ah, я вижу здесь несоответствие - нет, я не выполняю целочисленное деление, я выполняю двойное деление, а затем преобразовываю результат в целое число - совсем другое.
JerKimball
14

Деление осуществляется с помощью /оператора:

result = a / b;

Деление по модулю выполняется с помощью %оператора:

result = a % b;
Рион Уильямс
источник
1
+1: Удобный отказ от типа дает лучший ответ :-) Я считаю, что это работает и с System.Numeric.BigInteger в 4.0.
5
% -> как сказал Cor_Blimey, он возвращает остаток, а не модуль. Например: (-5% 3) == -2 [C #], -5 mod 3 = 1 [wolframalpha.com].
апокалипсис
2
Примечание: Modulo - это не то же самое, что Modulus. По модулю - остаток, по модулю - абсолютное значение.
Райан,
-4

Прочтите от пользователя два целых числа. Затем вычислите / отобразите остаток и частное,

// When the larger integer is divided by the smaller integer
Console.WriteLine("Enter integer 1 please :");
double a5 = double.Parse(Console.ReadLine());
Console.WriteLine("Enter integer 2 please :");
double b5 = double.Parse(Console.ReadLine());

double div = a5 / b5;
Console.WriteLine(div);

double mod = a5 % b5;
Console.WriteLine(mod);

Console.ReadLine();
Джеймс Домброски
источник