Comment puis-je calculer la division et le modulo pour les entiers en C #?


85

Comment puis-je calculer la division et le modulo pour les nombres entiers en C #?


15
C'est peut-être trop basique, mais c'est une vraie question ...

2
Un connexe poste et doit lire le blog pourquoi l' %opérateur est pas l'opérateur de module en C #.
RBT

Réponses:


123

Avant de poser des questions de ce type, veuillez consulter la documentation MSDN .

Lorsque vous divisez deux entiers, le résultat est toujours un entier. Par exemple, le résultat de 7/3 est 2. Pour déterminer le reste de 7/3, utilisez l'opérateur de reste ( % ).

int a = 5;
int b = 3;

int div = a / b; //quotient is 1
int mod = a % b; //remainder is 2

9
% renvoie le reste, pas le module (comme vous le faites remarquer). Ils ne sont pas la même chose et peuvent poser des problèmes lors du traitement de cas inhabituels (par exemple des indices négatifs). Cependant, il peut être utilisé comme l'opérateur de module lorsque l'on cherche simplement, par exemple, toutes les 10 itérations d'un indexeur faiblement positif. Peut-être pourriez-vous expliquer comment calculer le module réel?
Cor_Blimey

1
C'est vrai, j'ai lu des articles comme celui-ci, et j'ai eu des problèmes dans mon application :)
apocalypse

1
... Quel est l'intérêt de déclarer aet bsi vous n'allez pas les utiliser? : D
leviathanbadger

1
Peut-être que l'utilisateur cherchait (comme moi) une fonction DivRem, donc la question pourrait ne pas être aussi triviale qu'il n'y paraît à première vue. Merci @danodonovan
Tancredi

1
La réponse n'est pas aussi simple que cette réponse le prétend, comme d'autres l'ont également souligné, et peut conduire à des erreurs difficiles à déboguer. Voir /programming/10065080/mod-explanation
SansWit

88

Il y a aussi Math.DivRem

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

2
Cela devrait être la bonne réponse à mon avis, car elle fournit le quotient ET le reste dans une fonction. Je ne sais pas quelle approche fonctionne le mieux (en utilisant "a / b" pour obtenir le quotient, puis "a% b" pour obtenir le reste ou Math.DivRem), mais cette approche est certainement beaucoup plus agréable à lire (dans mon cas, j'ai besoin pour connaître le quotient et le reste) - merci!
Igor

2
@Igor merci, lorsque la question d'origine a été répondue, cette fonction n'existait pas! Cependant, l'existence de la fonction rend la remarque d'as-cii sur la vérification de la documentation un peu ridicule .... :)
danodonovan

5
Juste pour éviter toute confusion, Math.DivRemne calcule pas div et mod en une seule opération. Il est juste une fonction d'aide et son code source est exactement: public static int DivRem(int a, int b, out int result) { result = a%b; return a/b; }.
NightElfik

9
@NightElfik L'implémentation pourrait changer à l'avenir, et il est plus facile pour le runtime d'identifier un appel de méthode pour l'optimisation que disjoint divet reminstructions
kbolino

6
@kbolino C'est une excellente prédiction, car cela a changé , du moins dans .NET Core, pour diviser et soustraire. Et il y a d'autres optimisations prévues dans RyuJIT pour utiliser une seule instruction div x86, bien que les modifications JIT devraient également détecter les opérateurs %et /s'ils sont utilisés individuellement.
Bob

15

Fait amusant!

L'opération 'module' est définie comme:

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

Réf: Arithmétique modulaire

Vous pouvez donc lancer le vôtre, même si ce sera BEAUCOUP plus lent que l'opérateur% intégré:

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

Edit: wow, mal parlé ici à l'origine, merci @joren de m'avoir attrapé

Maintenant, je m'appuie sur le fait que division + cast-to-int en C # équivaut à Math.Floor(c'est- à -dire qu'il supprime la fraction), mais une implémentation "vraie" serait plutôt quelque chose comme:

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

En fait, vous pouvez voir les différences entre% et "vrai module" avec ce qui suit:

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);
}

Résultats:

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  

"Maintenant, je me fie au fait que la division entière en C # équivaut à Math.Floor (c'est-à-dire qu'elle supprime la fraction)" - Mais ce n'est pas le cas. La division entière arrondit vers zéro, Math.Floor arrondit vers l'infini négatif.
Joren

@Joren Désolé, mais non - essayez d'exécuter ceci: Enumerable.Range(0, 10).Select(x => (double)x / 10.0).Select(x => (int)x).ToList().ForEach(x => Console.WriteLine(x));- tous les 0
JerKimball

2
Premièrement, je parle de la division entière . Que se passe-t-il si vous effectuez une division en virgule flottante puis transtypez en entier n'est pas pertinent (même si cela donne le même résultat). Deuxièmement, je ne sais pas pourquoi vous vous attendriez à ce que les entiers entre 0 et 9 donnent autre chose que 0 après avoir divisé par 10 et tronqué à la partie entière. Si cela aboutissait à 1, cela serait arrondi à partir de zéro ou vers l' infini positif . Troisièmement, il n'y a aucune différence entre arrondir vers zéro et arrondir vers l'infini négatif pour les nombres positifs, de sorte que vous ne résolvez même pas le problème.
Joren

Math.Floor(-10.0 / 3.0)et ne-10 / 3 sont pas la même chose.
Joren

@joren ah, je vois la déconnexion ici - non, je n'effectue pas de division entière , j'effectue une double division, puis je transforme le résultat en entier - très différent.
JerKimball

14

La division est effectuée à l'aide de l' /opérateur:

result = a / b;

La division Modulo se fait à l'aide de l' %opérateur:

result = a % b;

1
+1: Le fait de laisser de côté le type en fait une meilleure réponse :-) Je crois que cela fonctionne aussi avec System.Numeric.BigInteger dans 4.0.

5
% -> comme l'a dit Cor_Blimey, il renvoie le reste et non le module. Par exemple: (-5% 3) == -2 [C #], -5 mod 3 = 1 [wolframalpha.com].
apocalypse

2
Remarque: Modulo n'est pas le même que Modulus. Modulo est le reste, Modulus est la valeur absolue.
Ryan

-4

Lisez deux entiers de l'utilisateur. Puis calculer / afficher le reste et le quotient,

// 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();
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.