Arrays 如何使用Eratoshenes筛设置第n素数中数组大小的上限?

Arrays 如何使用Eratoshenes筛设置第n素数中数组大小的上限?,arrays,rust,sieve-of-eratosthenes,Arrays,Rust,Sieve Of Eratosthenes,以n作为输入,我试图输出第n个素数。埃拉托斯坦筛似乎是一种很好的方法,但我对要筛选的阵列的大小有问题 我使用一个数组,其中每个成员都是1,并表示一个数字。如果筛子过滤掉该数字,则该值将更改为0,这意味着该数字不是素数。一旦到达值为1的第n个成员,将返回索引值 我试图为任何给定的n设置一个合理的数组大小。但我有两个问题 因为我似乎需要将数组的大小设置为常量,所以我找不到一种方法来使用n的大小来近似所需的数组大小。这意味着我总是使用10e6量级的数组,即使n很小 这种方法依赖于拥有一个大数组,因为它

以n作为输入,我试图输出第n个素数。埃拉托斯坦筛似乎是一种很好的方法,但我对要筛选的阵列的大小有问题

我使用一个数组,其中每个成员都是1,并表示一个数字。如果筛子过滤掉该数字,则该值将更改为0,这意味着该数字不是素数。一旦到达值为1的第n个成员,将返回索引值

我试图为任何给定的n设置一个合理的数组大小。但我有两个问题

  • 因为我似乎需要将数组的大小设置为常量,所以我找不到一种方法来使用n的大小来近似所需的数组大小。这意味着我总是使用10e6量级的数组,即使n很小

  • 这种方法依赖于拥有一个大数组,因为它使用早期值来更改后期值。这意味着,对于n>10e7,我的数组将破坏堆栈。有没有一种方法可以解决这个问题而不必陷入困境

  • 我尝试使用
    const
    解决第一个问题,如下所示:

    pub fn nth(n: u32) -> u32 {
        const ARRAY_SIZE : usize = f(n) // where f(n) is some approximation of required array size
        let mut primes: [usize; ARRAY_SIZE] = [1; ARRAY_SIZE];
        ...
    }
    
    但是,它并没有回避具有固定数组大小的要求

    有什么建议吗?此外,我是一个非常新的生锈和任何建议,使它更生锈一样欢迎

    下面是我的尝试,它有一个固定大小的数组,并使用一个可变数组大小处理n的值 不幸的是,堆栈上不可能有可变长度的数组。您可以使用向量在堆上分配它:

    让mut素数:Vec=Vec![正确;估计_大小(n)];
    
    估计所需尺寸 这个问题,虽然不是在生锈。其思想是使用第n个素数的上限公式:

    pn 对于
    u32
    ,可以使用浮点数来计算:

    // I'm making it a separate function for demonstration purposes. You might want to not do that.
    fn estimate_size(n: u32) -> usize {
        let n = n as f64;
        (n * (n * n.ln()).ln()).ceil() as usize
    }
    
    锈代码样式 就改进代码而言,我不明白为什么要使用
    usize
    s,因为您只存储0和1。对于
    bool
    ,这是一个完美的用例,它将导致内存使用量减少八倍

    output
    变量实际上不是必需的,最好使用
    return
    提前退出。然后您可以用
    unreachable!()

    另外,最里面的循环也可以这样写,我认为这样更好:

    for j in (2*i ..= primes.len()).step_by(i) {
        primes[j] = false;
    }
    

    筛子尺寸的标准公式是ln(n ln)表示n≥ 6.看

    如果使用天花板函数,即天花板(ln(n ln(n)),则公式适用于n>=3。但是,它不适用于1和2。对于n=1,在第二次ln()调用中取ln(0)时会出现错误,但它应该是2。对于n=2,筛子需要是3

    那么,检查是否使用{ 如果n<3{ (n+1)as usize }否则{ 设n=n为f64; (n*(n*n.ln()).ln()).ceil()用作 } }
    嘿,谢谢你的建议!我在上面的编辑中加入了你提到的一些更改。我很想听听你对它们的看法。
    // I'm making it a separate function for demonstration purposes. You might want to not do that.
    fn estimate_size(n: u32) -> usize {
        let n = n as f64;
        (n * (n * n.ln()).ln()).ceil() as usize
    }
    
    for j in (2*i ..= primes.len()).step_by(i) {
        primes[j] = false;
    }
    
    fn get_sieve_size(n: u32) -> usize {
        if n < 3 {
            (n + 1) as usize
        } else {
            let n = n as f64;
            (n * (n * n.ln()).ln()).ceil() as usize
        }
    }