是否有模数(不是余数)函数/运算?


71

在Rust(像大多数编程语言一样)中,%运算符执行余数运算,而不是模数运算。这些运算对负数有不同的结果

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

但是,我想要模数。

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


1
任何理由使用modulus代替的理由modulo(这是更常见的AFAICS)。
ideaman42

1
他们可能已经在使用模数一词的地方研究过,却不知道不同的机构在词汇上会有所不同。
OliverUv

对于2的幂,您可以执行-21&(4-1),因为它是整数。
AldaronLau

Answers:


35

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是一致的。

您不是第一个注意到这一点的人:


3
作为C / C ++程序员,我很尴尬,因为我也不知道它也不能%以C的方式工作……
Kapichu 2015年

3
这不是Rust的空白吗?
卡皮丘2015年

1
好吧,正如您所期望的,这不是数学家喜欢的。我不会说这是一个鸿沟,因为所有这一系列语言%只是剩余的。
JosEduSol

2
我会继续做下去%,但不支持模数吸收……
Kapichu

6
@JosEduSol在我撰写本文时,上面的答案显示(a % b) + b为一种计算模量的方法,但我很确定您要编写的内容是:((a % b) + b) % b
David J.

31

RFC 2196添加了一些与欧几里得除法有关的整数方法。具体来说,您要搜索的rem_euclid方法(的示例链接i32):

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

rustc 1.38.0(2019年9月27日发布)及更高版本中提供了此方法。


2
它们也适用于无符号变体,尽管无法从该文档中找出它们的作用。我还要提到div_euclid()完整性。但是无论如何这应该是选择的答案。
书呆子

10

不,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 }更好吗?
Alexx Roche

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.