In Rust (wie in den meisten Programmiersprachen) führt der %
Operator die Restoperation aus , nicht die Moduloperation . 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!
modulus
anstelle vonmodulo
(was häufiger AFAICS ist) zu verwenden.Antworten:
Soweit ich das beurteilen kann, gibt es keine modulare Rechenfunktion .
Dies geschieht auch in C, wo häufig die von Ihnen erwähnte Problemumgehung verwendet wird :
((a % b) + b) % b
.In C, C ++, D, C #, F # und Java
%
ist tatsächlich der Rest. In Perl ist Python oder Ruby%
der Modul.Sprachentwickler gehen nicht immer den "richtigen mathematischen Weg", daher scheinen Computersprachen aus der strengen Sicht des Mathematikers seltsam zu sein. Die Sache ist, dass sowohl der Modul als auch der Rest für verschiedene Verwendungszwecke korrekt sind.
Der Modul ist mathematischer, wenn Sie möchten, während der Rest (in der C-Familie) mit der gemeinsamen Ganzzahldivision übereinstimmt, die Folgendes erfüllt :
(a / b) * b + a % b = a
; Dies wird aus dem alten Fortran übernommen. Damit%
heißt der Rest besser, und ich nehme an, Rust stimmt mit C überein.Sie sind nicht der Erste, der dies bemerkt:
quelle
%
%
ist nur der Rest.%
dem Rest gehen, aber keine Unterstützung für Modul saugt ...(a % b) + b
eine Möglichkeit, den Modul zu berechnen, aber ich bin mir ziemlich sicher, was Sie schreiben wollten :((a % b) + b) % b
.RFC 2196 fügt einige ganzzahlige Methoden hinzu, die sich auf die euklidische Division beziehen. Insbesondere suchen Sie nach der
rem_euclid
Methode ( Beispiellink füri32
):println!("{}", -1i32 % 4); // -1 println!("{}", (-21i32).rem_euclid(4)); // 3
Diese Methode ist in
rustc 1.38.0
(veröffentlicht am 27.09.2019) und höher verfügbar .quelle
div_euclid()
Vollständigkeit halber möchte ich auch erwähnen . Dies sollte aber trotzdem die ausgewählte Antwort sein.Nein, Rust hat keinen eingebauten Modul, siehe diese Diskussion aus bestimmten Gründen an.
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 }
quelle
modulo_signed_ext_impl! { i8 i16 i32 i64 isize u8 u16 u32 u64 usize }
besser?Aus den anderen Antworten, die ich konstruiert habe:
fn n_mod_m <T: std::ops::Rem<Output = T> + std::ops::Add<Output = T> + Copy> (n: T, m: T) -> T { ((n % m) + m) % m } assert_eq!(n_mod_m(-21, 4), 3);
quelle
rem_euclid
möchten , wie ist es dann besser als das in Lukas Kalbertodts Antwort erwähnte integrierte Element ?