Подтвердить что ты не робот

Как создать функцию is_prime, которая является общей для разных целых типов?

Я просто взял погружение в 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 на главной странице, но я не уверен, как применять идеи черт к моей цели здесь.

4b9b3361

Ответ 1

Типичные типы номеров могут быть довольно неприятными для работы, но как только вы получите их повесить, они не будут слишком плохими, хотя и немного более подробными. Стандартными строительными блоками для таких методов являются черты ящик num из crates.io, наиболее заметно num, Zero и One, а также стандартная библиотека std::cmp::PartialOrd.

Числовые литералы не могут быть общими для любого числового типа; они должны выполняться с вызовом метода признаков; Zero::zero() и One::one() будет достаточно для большинство целей - здесь числа, которые мы хотим, - это 0, 1, 2, 3, 5 и 6, которые чрезвычайно достижимы с помощью этих строительных блоков. Вы могли бы также создать свою собственную черту со статическими методами, производящими эти значения, и реализовать их для любых цифровых типов, которые вам нравятся, но сделать это с помощью только того, что гарантировано num, является лучшей идеей.

Основная процедура заключается в том, чтобы указать ваши параметры типового типа как основанные на numPartialOrd, если вы пишете неравенства на значения этого типа, такие как i * i <= n), и замените любые числовые литералы на построенные начиная с нуля и единицы, так как демонстрирует полдюжины операторов 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
}

Ответ 2

Чтобы добавить к Крису Моргану ответ, вы можете использовать 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();