Wie kann ich Divide und Modulo für ganze Zahlen in C # berechnen?


84

Wie kann ich Division und Modulo für Ganzzahlen in C # berechnen?


14
Dies mag zu einfach sein, aber es ist eine echte Frage ...

2
Ein verwandter Beitrag und ein Blog, in dem gelesen werden muss, warum der %Operator nicht der Moduloperator in C # ist.
RBT

Antworten:


123

Bevor Sie Fragen dieser Art stellen, lesen Sie bitte die MSDN-Dokumentation .

Wenn Sie zwei Ganzzahlen teilen, ist das Ergebnis immer eine Ganzzahl. Das Ergebnis von 7/3 ist beispielsweise 2. Um den Rest von 7/3 zu bestimmen, verwenden Sie den Restoperator ( % ).

int a = 5;
int b = 3;

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

8
% gibt den Rest zurück, nicht den Modul (wie Sie hervorheben). Sie sind nicht dasselbe und können Probleme verursachen, wenn ungewöhnliche Fälle behandelt werden (z. B. negative Indizes). Es kann jedoch wie der Moduloperator verwendet werden, wenn nur nach jeder 10. Iteration eines schwach positiven Indexers gesucht wird. Vielleicht könnten Sie erklären, wie man den realen Modul berechnet?
Cor_Blimey

1
Es stimmt, ich habe solche Beiträge gelesen und hatte Probleme in meiner Bewerbung :)
Apokalypse

1
... Was genau ist der Sinn der Erklärung aund bwenn Sie sie nicht verwenden werden? : D
Leviathanbadger

@ Aboveyou00: das für dich behoben!
Sir Crispalot

1
Die Antwort ist nicht so einfach wie diese Antwort behauptet, wie andere ebenfalls betont haben, und kann zu schwer zu debuggenden Fehlern führen. Siehe /programming/10065080/mod-explanation
SansWit

86

Es gibt auch Math.DivRem

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

2
Dies sollte meiner Meinung nach die richtige Antwort sein, da es den Quotienten UND den Rest in einer Funktion liefert. Ich bin mir nicht sicher, welcher Ansatz besser funktioniert (mit "a / b", um den Quotienten zu erhalten, und dann mit "a% b", um den Rest oder Math.DivRem zu erhalten), aber dieser Ansatz ist sicherlich viel besser zu lesen (in meinem Fall brauche ich Quotient und Rest kennen) - danke!
Igor

2
@Igor danke, als die ursprüngliche Frage beantwortet wurde, existierte diese Funktion nicht! Die Existenz der Funktion lässt jedoch die Bemerkung von as-cii über das Überprüfen der Dokumentation etwas albern aussehen .... :)
danodonovan

5
Nur um Verwirrung zu vermeiden, werden Math.DivRemdiv und mod nicht in einer Operation berechnet. Es ist nur eine Hilfsfunktion und der Quellcode lautet genau : public static int DivRem(int a, int b, out int result) { result = a%b; return a/b; }.
NightElfik

9
@ NightElfik Die Implementierung könnte sich in Zukunft ändern, und es ist für die Laufzeit einfacher, einen Methodenaufruf für die Optimierung zu identifizieren als disjunkte divund remAnweisungen
kbolino

5
@kbolino Das ist eine große Vorhersage, da sie hat geändert , zumindest in .NET - Core, zu teilen und subtrahieren. In RyuJIT sind weitere Optimierungen geplant, um einen einzelnen x86-Div-Befehl zu verwenden. Zugegebenermaßen sollten die JIT-Änderungen auch die Operatoren %und erkennen /, wenn sie einzeln verwendet werden.
Bob

14

Die Division erfolgt mit dem /Operator:

result = a / b;

Die Modulo-Division erfolgt mit dem %Operator:

result = a % b;

1
+1: Wenn Sie den Typ bequem weglassen, ist dies eine bessere Antwort :-) Ich glaube, dass dies auch mit System.Numeric.BigInteger in 4.0 funktioniert.

5
% -> Wie Cor_Blimey sagte, wird der Rest und nicht der Modul zurückgegeben. Zum Beispiel: (-5% 3) == -2 [C #], -5 mod 3 = 1 [wolframalpha.com].
Apokalypse

2
Hinweis: Modulo ist nicht dasselbe wie Modul. Modulo ist der Rest, Modul ist der absolute Wert.
Ryan

14

Lustige Tatsache!

Die 'Modul'-Operation ist definiert als:

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

Ref: Modulare Arithmetik

Sie können also Ihre eigenen würfeln, obwohl dies weitaus langsamer ist als der eingebaute% -Operator:

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

Edit: wow, hier ursprünglich ziemlich schlecht geschrieben, danke @joren, dass du mich erwischt hast

Jetzt verlasse ich mich hier auf die Tatsache, dass Division + Cast-to-Int in C # äquivalent ist Math.Floor(dh den Bruchteil fallen lässt), aber eine "wahre" Implementierung wäre stattdessen so etwas wie:

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

Tatsächlich können Sie die Unterschiede zwischen% und "wahrem Modul" wie folgt erkennen:

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

Ergebnisse:

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  

"Jetzt verlasse ich mich hier auf die Tatsache, dass die Ganzzahldivision in C # Math.Floor entspricht (dh den Bruchteil fallen lässt)" - aber das ist es nicht. Integer Divison rundet gegen Null, Math.Floor rundet gegen negative Unendlichkeit.
Joren

@ Joren Sorry, aber nein - versuchen Sie dies: Enumerable.Range(0, 10).Select(x => (double)x / 10.0).Select(x => (int)x).ToList().ForEach(x => Console.WriteLine(x));- alle
Nullen

2
Zunächst spreche ich über die Ganzzahldivision . Was passiert, wenn Sie eine Gleitkommadivision durchführen und dann in eine Ganzzahl umwandeln, ist irrelevant (obwohl dies das gleiche Ergebnis liefert). Zweitens bin ich mir nicht sicher, warum Sie erwarten würden, dass ganze Zahlen zwischen 0 und 9 etwas anderes als 0 ergeben, nachdem Sie durch 10 geteilt und auf den ganzzahligen Teil abgeschnitten haben. Wenn dies zu 1 führen würde, würde dies von Null weg oder in Richtung positive Unendlichkeit runden . Drittens gibt es keinerlei Unterschied zwischen einer Rundung gegen Null und einer Rundung gegen negative Unendlichkeit für positive Zahlen, sodass Sie das Problem nicht einmal ansprechen.
Joren

Math.Floor(-10.0 / 3.0)und -10 / 3sind nicht dasselbe.
Joren

@joren ah, ich sehe die Trennung hier - nein, ich führe keine Ganzzahldivision durch , ich führe eine Doppeldivision durch und wandle dann das Ergebnis in eine Ganzzahl um - ganz anders.
JerKimball

-4

Lesen Sie zwei Ganzzahlen vom Benutzer. Berechnen / zeigen Sie dann den Rest und den Quotienten an.

// 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();
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.