是否存在模数(非余数)函数/运算?

时间:2015-07-03 15:39:32

标签: rust modulo

在Rust中(与大多数编程语言一样),%运算符执行余数运算,而不是模数运算。这些operations have different results for negative numbers

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

但是,我想要模数。

我找到了一个解决方法((a % b) + b) % b,但如果已有功能,我不想重新发明轮子!

4 个答案:

答案 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);