我刚刚深入研究了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
}
能够将isize
,i64
,usize
等作为参数传递给我需要什么?我已经阅读了主页上的Rust guide,但我不确定如何将特征的想法应用到我的目标中。
答案 0 :(得分:25)
通用数字类型可能会非常麻烦,但是一旦你掌握了它们,它们就不会太糟糕,虽然更加冗长。这些方法的标准构建块是来自crates.io的the num
crate中的特征,最值得注意的是Num
,Zero
和One
,以及标准库{{3} }}。
数字文字不能超过任何数字类型;它们必须用特征方法调用完成; std::cmp::PartialOrd
和Zero::zero()
足以满足大多数目的 - 这里我们想要的数字是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
}
答案 1 :(得分:15)
要添加到Chris Morgan的答案,您可以使用num::NumCast::from
转换为使用Zero
和One
不合适的通用数字类型。在你的情况下:
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();