如何创建一个在各种整数类型上通用的is_prime函数?

gai*_*epr 29 traits rust

我刚刚深入研究了Rust,并希望制作一些通用的基本数学函数.我有以下is_prime功能:

fn is_prime(n: i64) -> bool {
    if n == 2 || n == 3 {
        return true;
    } else if n % 2 == 0 || n % 3 == 0 {
        return false;
    }

    let mut i = 5i64;
    let mut w = 2i64;
    while i*i <= n {
        if n % i == 0 {
            return false;
        }
        i += w;
        w = 6 - w;
    }
    true
}
Run Code Online (Sandbox Code Playgroud)

那么将会对我来说,能够通过isize,i64,usize,等作为参数?我已经阅读了主页上的Rust指南,但我不确定如何将特征的想法应用到我的目标中.

Chr*_*gan 25

通用数字类型可能会非常麻烦,但是一旦你掌握了它们,它们就不会太糟糕,虽然更加冗长.该标准积木这样的方法是在特质num箱子从crates.io,最值得注意的是Num,ZeroOne,以及标准库的std::cmp::PartialOrd.

数字文字不能超过任何数字类型; 它们必须用特征方法调用完成; Zero::zero()并且One::one()足以满足大多数目的 - 这里我们想要的数字是0,1,2,3,5和6,这些构建块可以显着地实现.您也可以使用静态方法创建自己的特性来生成这些值,并为您喜欢的任何数字类型实现它,但是使用保证Num的更好的想法来实现它.

基本过程是将您的泛型类型参数指定为基于Num(并且PartialOrd如果您在该类型的值上写出不等式,例如i * i <= n),并将任何数字文字替换为从0和1构造的数字文字,作为此处的半打let语句下面的方法开始演示.这通常就足够了.

以下是您对此特定方法的最终结果:

// You’ll also need the appropriate dependencies.num addition to Cargo.toml
extern crate num;

use num::Num;

fn is_prime<N: Num + PartialOrd + Copy>(n: N) -> bool {
    let _0 = N::zero();
    let _1 = N::one();
    let _2 = _1 + _1;
    let _3 = _2 + _1;
    let _5 = _2 + _3;
    let _6 = _3 + _3;
    if n == _2 || n == _3 {
        return true;
    } else if n % _2 == _0 || n % _3 == _0 {
        return false;
    }

    let mut i = _5;
    let mut w = _2;
    while i * i <= n {
        if n % i == _0 {
            return false;
        }
        i = i + w;
        w = _6 - w;
    }
    true
}
Run Code Online (Sandbox Code Playgroud)

  • 除了使用"Num"特征作为约束之外,还可以使用实际需要的基本特征:`N:PartialEq + PartialOrd + Add <N,N> + Sub <N,N> + Mul <N, N> + Rem <N,N> + One + Zero`."Num"只是一个方便的捷径. (7认同)

小智 15

要添加到Chris Morgan的答案,您可以使用num::NumCast::from转换为使用ZeroOne不合适的通用数字类型.在你的情况下:

use num::{Num, NumCast};

fn is_prime<N: Num + Ord + NumCast + Copy>(n: N) -> bool {
    let _0: N = NumCast::from(0usize).unwrap();
    let _1: N = NumCast::from(1usize).unwrap();
    let _2: N = NumCast::from(2usize).unwrap();
    let _3: N = NumCast::from(3usize).unwrap();
    let _4: N = NumCast::from(4usize).unwrap();
    let _5: N = NumCast::from(5usize).unwrap();
    let _6: N = NumCast::from(6usize).unwrap();
Run Code Online (Sandbox Code Playgroud)