在Rust(像大多数编程语言一样)中,%
运算符执行余数运算,而不是模数运算。这些运算对负数有不同的结果:
-21 modulus 4 => 3
-21 remainder 4 => -1
println!("{}", -21 % 4); // -1
但是,我想要模数。
我找到了一种解决方法((a % b) + b) % b
,但是如果已有功能,我不想重新发明轮子!
在Rust(像大多数编程语言一样)中,%
运算符执行余数运算,而不是模数运算。这些运算对负数有不同的结果:
-21 modulus 4 => 3
-21 remainder 4 => -1
println!("{}", -21 % 4); // -1
但是,我想要模数。
我找到了一种解决方法((a % b) + b) % b
,但是如果已有功能,我不想重新发明轮子!
Answers:
Rust中是否有模数(不是余数!)函数/运算?
据我所知,没有模块化算术函数。
这在C语言中也会发生,在C语言中通常会使用您提到的解决方法:((a % b) + b) % b
。
%
实际上,在C,C ++,D,C#,F#和Java中,其余的部分。在Perl,Python或Ruby中,%
是模数。
语言开发人员并不总是采用“正确的数学方法”,因此从严格的数学家的角度来看,计算机语言可能看起来很奇怪。问题是模数和余数对于不同的用途都是正确的。
模量更数学,如果你喜欢,而其余的(在C家族)是常见的整数除法满足一致:(a / b) * b + a % b = a
; 这是从旧的Fortran中采用的。所以%
最好称为余数,我认为Rust与C是一致的。
您不是第一个注意到这一点的人:
%
以C的方式工作……
%
只是剩余的。
%
,但不支持模数吸收……
(a % b) + b
为一种计算模量的方法,但我很确定您要编写的内容是:((a % b) + b) % b
。
不,Rust没有内置模数,请参阅此讨论出于某些原因。
这是一个可能方便的示例:
///
/// 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 }
modulo_signed_ext_impl! { i8 i16 i32 i64 isize u8 u16 u32 u64 usize }
更好吗?
根据其他答案,我构造了:
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);
rem_euclid
Lukas Kalbertodt的答案中提到的内置函数更好吗?
modulus
代替的理由modulo
(这是更常见的AFAICS)。