Як я можу розрахувати ділення та модуль для цілих чисел у C #?


85

Як я можу обчислити ділення та модуль для цілих чисел у 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

9
% повертає залишок, а не модуль (як ви вказуєте). Вони не одне і те ж і можуть спричинити проблеми при розгляді незвичних випадків (наприклад, негативні показники). Однак його можна використовувати як оператор модуля, коли просто шукаємо, наприклад, кожну 10-ю ітерацію слабо позитивного індексатора. Можливо, ви могли б пояснити, як розрахувати реальний модуль?
Cor_Blimey

1
Правда, я читав такі публікації, і в моїй заявці виникли проблеми :)
апокаліпсис

1
... Який саме сенс заявляти, aі bякщо ви не збираєтесь ними користуватися? : D
leviathanbadger

1
Можливо, користувач шукав (як і я) функцію DivRem, тому питання може бути не таким тривіальним, як здається на перший погляд. Спасибі @danodonovan
Tancredi

1
Відповідь не така проста, як стверджує ця відповідь, на що також вказували інші, і може призвести до важких для налагодження помилок. Дивіться /programming/10065080/mod-explanation
SansWit

88

Є також Math.DivRem

quotient = Math.DivRem(dividend, divisor, out remainder);

2
На мою думку, це повинна бути правильна відповідь, оскільки вона забезпечує частку І залишок в одній функції. Я не впевнений, який підхід працює ефективніше (використання "a / b", щоб отримати коефіцієнт, а потім "a% b", щоб отримати залишок, або Math.DivRem), але цей підхід, безумовно, набагато приємніше читати (у моєму випадку мені потрібно знати і частку, і залишок) - дякую!
Ігор

2
@Igor дякую, коли відповіли на вихідне запитання, ця функція не існувала! Однак існування функції робить зауваження as-cii щодо перевірки документації виглядає дещо безглуздо .... :)
danodonovan

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 заплановано подальшу оптимізацію використання однієї інструкції div 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 за те, що мене зловили

Тепер тут я покладаюсь на той факт, що розділення + вкладання в int у 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  

"Зараз тут я покладаюся на той факт, що цілочисельне ділення в C # еквівалентно Math.Floor (тобто воно знижує дріб)" - Але це не так. Ціле ділення округляється до нуля, Math.Foor окружнює до негативної нескінченності.
Йорен

@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 , які будуть округляти в сторону від нуля або по напрямку до позитивної нескінченності. По-третє, немає ніякої різниці між округленням до нуля та округленням до негативної нескінченності для позитивних чисел, тому ви навіть не вирішуєте проблему.
Йорен

Math.Floor(-10.0 / 3.0)і -10 / 3це НЕ те ж саме.
Йорен

@joren ах, я бачу тут розрив зв'язку - ні, я не виконую цілочисельне ділення, я виконую подвійне ділення, а потім додаю результат до цілого числа - дуже різний.
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. 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();
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.