Einleitung: Warum ist die Frage nach dem Modul so beliebt?
\n\nWenn Sie jemals Code in Rust geschrieben haben und auf negative Zahlen gestoßen sind, haben Sie sich sicherlich gefragt: „Wo ist die Modulfunktion?“. Auf Stack Overflow hat diese Frage tausende Aufrufe, und das zu Recht. Der Grund ist, dass der Operator % in Rust nicht der Modul (modulus) ist, sondern der Rest der Division (remainder). Der Unterschied ist subtil, aber kritisch, besonders in Algorithmen, Kryptographie oder bei der Arbeit mit zyklischen Strukturen.
In diesem Artikel werden wir untersuchen, wie sich der mathematische Modul vom Rest unterscheidet, wie Rust mit negativen Zahlen umgeht und wie Sie Ihre eigene Funktion zur Berechnung des wahren Moduls schreiben können. Der Artikel richtet sich an Anfänger, ist aber auch für erfahrene Entwickler nützlich, die ihr Wissen auffrischen möchten.
\n\nKurze Zusammenfassung
\n- \n
- Was ist Modul und Rest: der mathematische Unterschied \n
- Warum
%in Rust nicht der Modul ist \n - Wie man eine Modulfunktion in Rust schreibt \n
- Beispiele aus der Praxis: zyklische Indizes und Hashes \n
- Schlussfolgerungen und praktische Tipps \n
Mathematik: Modul vs. Rest
\n\nBeginnen wir mit den Grundlagen. In der Mathematik ist der Modul (modulus) eine Operation, die eine nicht-negative Zahl zurückgibt, die kleiner als der Divisor ist. Zum Beispiel:
\n- \n
7 mod 3 = 1(7 geteilt durch 3 ergibt Rest 1) \n -7 mod 3 = 2(weil -7 = 3 * (-3) + 2) \n
Der Rest der Division (remainder) ist das, was nach der ganzzahligen Division übrig bleibt. In den meisten Programmiersprachen (C, C++, Java, Rust) gibt der Operator % genau diesen Rest zurück, der negativ sein kann, wenn der Dividend negativ ist. Beispiel:
- \n
7 % 3 = 1(übereinstimmend) \n -7 % 3 = -1(in Rust, weil -7 / 3 = -2, Rest -1) \n
Wozu ist das gut? Stellen Sie sich vor, Sie schreiben ein Programm für eine Uhr: Zeit 0–23. Wenn es jetzt 22 Uhr ist und Sie 5 Stunden hinzufügen, erhalten Sie 3 Uhr morgens. Das funktioniert mit dem Modul: (22 + 5) mod 24 = 3. Wenn Sie jedoch den Rest verwenden, funktioniert das bei negativen Werten nicht. Zum Beispiel ergibt (-3) % 24 in Rust -3, nicht 21.
Warum der Operator % in Rust der Remainder ist
\n\nIn Rust ist der Operator % als Rest der Division definiert. Dies ist in der Dokumentation und im Verhalten der Standardbibliothek festgelegt. Der Grund ist historisch: So ist es in C und vielen anderen Sprachen. Rust folgt dem Prinzip „explizit ist besser als implizit“, aber hier tappen Anfänger oft in die Falle.
fn main() {\n println!("7 % 3 = {}", 7 % 3); // 1\n println!("-7 % 3 = {}", -7 % 3); // -1\n println!("7 % -3 = {}", 7 % -3); // 1 (ja, das Vorzeichen des Divisors hat keinen Einfluss)\n println!("-7 % -3 = {}", -7 % -3); // -1\n}\n\nBeachten Sie: Das Vorzeichen des Ergebnisses stimmt immer mit dem Vorzeichen des Dividenden überein. Das ist nicht der Modul. Für den wahren Modul muss das Ergebnis immer nicht-negativ sein.
\n\nWie schreibt man eine Funktion für den wahren Modul in Rust?
\n\nDie Standardbibliothek von Rust bietet keine eingebaute Funktion für den Modul (im Gegensatz zu Python, wo % als Modul funktioniert). Aber es ist sehr einfach, eine zu schreiben. Hier ist die gebräuchlichste Methode – über den Rest mit Korrektur.
Funktion modulus für ganze Zahlen
\n\nfn modulus(a: i32, b: i32) -> i32 {\n let r = a % b;\n if r < 0 { r + b.abs() } else { r }\n}\n\nfn main() {\n println!("modulus(7, 3) = {}", modulus(7, 3)); // 1\n println!("modulus(-7, 3) = {}", modulus(-7, 3)); // 2\n println!("modulus(7, -3) = {}", modulus(7, -3)); // 1 (Modul ist immer nicht-negativ)\n println!("modulus(-7, -3) = {}", modulus(-7, -3)); // 2\n}\n\nWie funktioniert das? Wir nehmen den Rest a % b. Wenn er negativ ist, addieren wir den Absolutwert des Divisors