【问题标题】:Should I keep this function for finding nth prime or can this be optimized?我应该保留这个函数来寻找第 n 个素数还是可以优化?
【发布时间】:2020-09-06 17:41:28
【问题描述】:

我们有一个与 Prime 相关的编码作业,我的朋友编写了这段代码。它很长,我不太了解它,并且有goto,我认为这是不受欢迎的,所以我不知道。可以帮助决定我们是否应该保留它?

int getNth (int nth){
    vector<int> prime;
    int sievelmt = nth*10;
    int i,j;
    func:
    vector<int> sieve(sievelmt, -1);
    prime.push_back(2); if (nth == 1) return 2;
    prime.push_back(3); if (nth == 2) return 3;
    prime.push_back(5); if (nth == 3) return 5;
    for (i = 2; i <= sievelmt; i++)
    {
        if (i%2==0||i%3==0||i%5==0) continue;
        if (sieve[i] == -1)
        {
            prime.push_back(i); if (prime.size()==nth) return prime[prime.size()-1];
            for ( j = 1; i*j <= sievelmt; j++) sieve[i*j]=j;
        }
        else continue;
    }    
    sievelmt *= 10;
    sieve.clear(); prime.clear();
    goto func;
    return -1;
}

【问题讨论】:

  • 那么标签和goto 可以很容易地被无限循环替换。永远不要使用标签和goto 作为循环。
  • 对于这段代码我该怎么做?
  • 代码不清楚的时候第一个问的是作者。你问你朋友了吗?
  • 他说找到第 n 个素数。我们不确定这段代码是否正确。
  • 嗯,这是主观的,但我个人觉得他扔掉所有之前的中间结果并在发现他的向量太小时重新开始有点蹩脚。

标签: c++ algorithm math primes


【解决方案1】:

算法的核心是这一行:

for ( j = 1; i*j <= sievelmt; j++) sieve[i*j]=j;

对于给定的i,它填充数组sieve 的位置,这些位置是i 的倍数,具有倍数的等级。想象一下i=7,然后是sieve[7]=1sieve[14]=2sieve[21]=3,等等

这是 Eratosthène 筛子的基础,这是一种非常古老的算法(Eratosthène 是一位古希腊科学家),用于寻找素数。如果您使i 从 2 变化到某个值,那么这将标记索引不是素数的每个位置。最后,每个未标记的位置都是素数。让我们看看:

  • i=2.1.2.3.4.5.6.7.
  • i=3.112.2.435.4.75, 3 是素数(第一次访问位置 3)
  • i=4.111.2.235.3.75
  • i=5.11112.232.3.73, 5 是素数(第一次访问位置 5)
  • i=6.11111.232.3.73
  • i=7.111111232.3.23, 7 是素数
  • i=8.111111132.3.23
  • i=9.111111112.3.23
  • i=10.111111111.3.23
  • i=11.11111111113.23,11 是素数

为什么这里有goto?别担心,goto 存在许多危险的用法,但不是。如果您对那个替换感到不满意:

func:
...
goto func;

与:

while(1) {
...
}

所以真正的问题是为什么还有一些“无限”循环?

这是因为您正在寻找第 n 个素数,但您无法轻松确定数组必须多长时间才能捕获第 n 个素数...所以该实现只是尝试增加大小.第一次,算法希望第 n 个素数在大小为 10*n 的数组中,如果不够,则将大小乘以 10,一次又一次,直到第 n 个素数成为在。

我可以优化一下吗?

当然,有一些小技巧。首先你可以看到,如果给定的i 可以被 2、3 或 5 整除,那么它就不能是素数。这已经实现了:

if (i%2==0||i%3==0||i%5==0) continue;

那么你可能会说,好吧,如果能被 7 或 11 或 13 等整除(意味着被任何其他素数),它是一样的!我不会告诉你更多,但当然你可以转换该算法以确定给定的i 是否可以被任何小于i 的素数整除(可能通过在数组中存储稍微不同的值)。

【讨论】:

  • 非常感谢。所以每次我检查它是否可以被素数整除所需的计算减少1 /素数对吗?所以在 7 或 13 之后会比只运行循环更好吗?我可以创建一个循环来测试所有以前的素数我应该这样做吗?
  • 您不必循环测试它。如果它可以被素数整除,那么它已经被查看过......(看?)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-11-26
  • 2012-04-25
  • 1970-01-01
  • 2014-01-27
  • 2023-03-03
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多