在Rust中(与大多数编程语言一样),%
运算符执行余数运算,而不是模数运算。这些operations have different results for negative numbers:
-21 modulus 4 => 3
-21 remainder 4 => -1
println!("{}", -21 % 4); // -1
但是,我想要模数。
我找到了一个解决方法((a % b) + b) % b
,但如果已有功能,我不想重新发明轮子!
答案 0 :(得分:18)
Rust中有模数(非余数!)函数/操作吗?
据我所知,没有模运算功能。
这也发生在C中,通常使用您提到的解决方法:(a % b) + b
。
在C,C ++,D,C#,F#和Java中,%
实际上是余数。在Perl,Python或Ruby中,%
是模数。
语言开发人员并不总是采用“正确的数学方式”,因此从严格的数学家观点来看,计算机语言可能看起来很奇怪。问题是模数和余数都适用于不同的用途。
如果你愿意,模数更具数学性,而余数(在C族中)与满足的公共整数除法一致:(a / b) * b + a % b = a
;这是从旧的Fortran采用的。所以%
更好地称为余数,我认为Rust与C一致。
您不是第一个注意到这一点:
答案 1 :(得分:5)
不,Rust没有内置模数,由于某些原因,请参阅this discussion。
这是一个可能很方便的例子:
///
/// 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 }
答案 2 :(得分:3)
RFC 2196添加了一些与欧几里得除法有关的整数方法。具体来说,您正在搜索rem_euclid
方法(example link for i32
)
println!("{}", -1i32 % 4); // -1
println!("{}", (-21i32).rem_euclid(4)); // 3
此方法在rustc 1.38.0
(于2019-09-27发布)及更高版本中可用。
答案 3 :(得分:-1)
从其他答案中我得出结论:
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);