2014-11-07 14 views
22

Tôi vừa đi sâu vào Rust và muốn thực hiện một số hàm toán học cơ bản chung chung. Tôi có is_prime chức năng sau:Làm thế nào tôi có thể tạo một hàm is_prime chung chung với các kiểu số nguyên khác nhau?

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 
} 

gì nó sẽ đưa cho tôi để có thể vượt qua isize, i64, usize vv như các đối số? Tôi đã đọc qua số Rust guide trên trang chủ nhưng tôi không chắc chắn cách áp dụng các ý tưởng về đặc điểm cho mục tiêu của mình tại đây.

Trả lời

22

Các loại số chung có thể khá phiền toái khi làm việc, nhưng một khi bạn nhận được hàng thì chúng không có xu hướng quá tệ, mặc dù tiết kiệm hơn một chút. Các khối xây dựng tiêu chuẩn cho các phương pháp như vậy là các đặc điểm trong số the num crate từ crates.io, đáng chú ý nhất là Num, ZeroOne, cũng như thư viện chuẩn của std::cmp::PartialOrd.

Chữ số không thể chung chung với bất kỳ loại số nào; chúng phải được thực hiện với một cuộc gọi phương thức đặc điểm; Zero::zero()One::one() sẽ đủ cho hầu hết các mục đích — ở đây các số mà chúng tôi muốn là 0, 1, 2, 3, 5 và 6, có thể đạt được với các khối xây dựng này. Bạn cũng có thể làm cho đặc điểm của riêng bạn với các phương pháp tĩnh tạo ra các giá trị này và triển khai nó cho bất kỳ loại số nào bạn thích, nhưng thực hiện nó chỉ với những gì được đảm bảo bởi Num là một ý tưởng tốt hơn.

Thủ tục cơ bản là để xác định các thông số chung chung kiểu của bạn như được dựa trên Num (và PartialOrd nếu bạn viết bất bình đẳng về giá trị của loại hình đó, chẳng hạn như i * i <= n), và thay thế bất kỳ chữ số với những người xây dựng từ con số không và một, như nửa tá các câu lệnh let khi bắt đầu phương thức dưới đây minh họa. Điều đó thường sẽ là đủ.

Đây là những gì bạn kết thúc với cho phương pháp đặc biệt này:

// 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 
} 
+5

Thay vì sử dụng 'Num' đặc điểm là một hạn chế, nó cũng có thể sử dụng những đặc điểm cơ bản mà đang thực sự cần thiết: 'N: PartialEq + PartialOrd + Thêm + Sub + Mul + Rem + One + Zero'. 'Num' chỉ đơn giản là một phím tắt thuận tiện. –

15

Để thêm vào câu trả lời Chris Morgan, bạn có thể sử dụng num::NumCast::from để cast cho một loại số chung nơi sử dụng ZeroOne sẽ là không phù hợp. Trong trường hợp của bạn:

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(); 
Các vấn đề liên quan