web-dev-qa-db-de.com

Gibt es eine Modul- (nicht Rest-) Funktion / Operation?

In Rust (wie in den meisten Programmiersprachen) führt der Operator % Die Operation Rest aus, nicht die Operation Modul Bedienung. Diese Operationen haben unterschiedliche Ergebnisse für negative Zahlen :

-21 modulus 4 => 3
-21 remainder 4 => -1
println!("{}", -21 % 4); // -1

Ich möchte jedoch den Modul.

Ich habe eine Problemumgehung gefunden ((a % b) + b) % b, Aber ich möchte das Rad nicht neu erfinden, wenn es dafür bereits eine Funktion gibt!

40
Kapichu

Gibt es in Rust eine E-Modul-Funktion (kein Rest!)?

Soweit ich das beurteilen kann, gibt es keine modulare Rechenfunktion .

Dies geschieht auch in C, wo es üblich ist, die von Ihnen erwähnte Problemumgehung zu verwenden: (a % b) + b.

In C, C++, D, C #, F # und Java wird % ist in der Tat der Rest. In Perl Python oder Ruby, % ist der Modul.

Sprachentwickler gehen nicht immer den "richtigen mathematischen Weg", so dass Computersprachen aus der Sicht des Mathematikers seltsam erscheinen können. Die Sache ist, dass sowohl der Modul als auch der Rest für verschiedene Anwendungen korrekt sind.

Der Modul ist mathematischer, wenn Sie möchten, während der Rest (in der C-Familie) mit der gewöhnlichen Ganzzahldivision übereinstimmt, die Folgendes erfüllt: (a / b) * b + a % b = a; Dies ist aus dem alten Fortran übernommen. So % heißt besser der Rest, und ich nehme an Rust steht im Einklang mit C.

Sie sind nicht der erste, der dies bemerkt:

20
JosEduSol

Nein, Rust hat keinen eingebauten Modul, siehe diese Diskussion aus einigen Gründen warum.

Hier ist ein Beispiel, das nützlich sein könnte:

///
/// Modulo that handles negative numbers, works the same as Python's `%`.
///
/// eg: `(a + b).modulo(c)`
///
pub trait ModuloSignedExt {
    fn modulo(&self, n: Self) -> Self;
}
macro_rules! modulo_signed_ext_impl {
    ($($t:ty)*) => ($(
        impl ModuloSignedExt for $t {
            #[inline]
            fn modulo(&self, n: Self) -> Self {
                (self % n + n) % n
            }
        }
    )*)
}
modulo_signed_ext_impl! { i8 i16 i32 i64 }
6
ideasman42

RFC 2196 fügt ein paar ganzzahlige Methoden hinzu, die sich auf die euklidische Teilung beziehen. Insbesondere die rem_euclid method ( Beispiellink für i32 ) ist was Sie suchen:

println!("{}", -1i32 % 4);                // -1
println!("{}", (-21i32).rem_euclid(4));   // 3

Diese Methode ist verfügbar in rustc 1.38.0 (veröffentlicht am 27.09.2019) und höher.

0