如何以更有效的方式检查一个数字是否是素数?

How to check if a number is prime in a more efficient manner?

本文关键字:一个 数字 是否是 有效 检查 方式      更新时间:2023-10-16

所以我有以下问题。他们给了我一个带有n个数字的数组,我必须使用"Divide et Impera"打印它是否包含任何素数。我解决了这个问题,但它只得到了 70/100,因为它效率不高(他们说(。

#include <iostream>
using namespace std;
bool isPrime(int x){
if(x == 2) return false;
for(int i = 2; i <= x/2; ++i)
if(x%i==0) return false;
return true;
}
int existaP(int a[], int li, int ls){
if(li==ls)
if(isPrime(a[li]) == true) return 1;
else return 0;
else  return existaP(a, li, (li+ls)/2)+existaP(a, (li+ls)/2+1, ls);      
}
int main(){
int n, a[10001];
cin >> n;
for(int i = 1; i<=n; ++i) cin >> a[i];
if(existaP(a,1,n) >= 1) cout << "Y";
else cout << "N";
return 0;
}

这里挂得最低的果实是你的停止条件

i <= x/2

可以替换为

i * i <= x

注意确保您不会溢出int。这是因为你只需要上升到x的平方根,而不是半途而废。也许i <= x / i更好,因为这可以避免溢出;尽管以牺牲在某些平台上可能相对昂贵的部门为代价。

您的算法在x == 2上也有缺陷,因为您的返回值不正确。如果您放弃该额外的测试会更好,因为随后的循环会覆盖它。

这是检查素数的有效方法。

bool isPrime(int num) {
if(num <= 1) return false;
if (num <= 3)  return true; 

int range = sqrt(num);
// This is checked so that we can skip 
// middle five numbers in below loop 
if (num % 2 == 0 || num % 3 == 0) 
return false; 

for (int i = 5; i <= range; i += 6) 
if (num % i == 0 || num % (i + 2) == 0) 
return false; 

return true;
}

一个标准的方法(也许..?(只是检查从i = 0到sqrt(数字(

bool isPrime(int num){
if(num == 1) return false;
for(int i = 2;i<=sqrt(num);i++){
if(num % i == 0) return false;
}
return true;
}
bool isprime(int x)
{
if(x <= 1) return false;
if(x == 2 || x == 3) return true;
if(x % 2 == 0 || x % 3 == 0) return false;
if((x - 1) % 6 != 0 && (x + 1) % 6 != 0) return false;
for(int i = 5; i * i <= x; i += 6)
{
if(x % i == 0 || x % (i + 2) == 0) return false;
}
return true;
}

如果需要为特定范围打印素数或确定一个数字是否是素数,则埃拉托色尼算法的筛子可能更可取,因为它在时间复杂度O( n * log2( log2(n) ) )方面非常有效,但是如果数字超过一定的内存限制,该算法的空间复杂度可能会导致问题。

我们可以优化这个更简单的算法,它的时间复杂度为O(n1/2)通过引入一些基于此 thoerem 的额外检查,如上isprime code block所示。

尽管在空间限制下,Erathosthenes的筛子算法在时间复杂度方面是有效的,但可以使用上述提供的isprime code block,并且Erathosthenes的筛子算法有许多变体,性能要好得多,如本链接所述。

存在更多的算法,但在解决编码挑战方面,这个更简单、更方便。您可以通过单击以下链接了解有关它们的更多信息:

  1. https://www.quora.com/Whats-the-best-algorithm-to-check-if-a-number-is-prime
  2. https://www.baeldung.com/cs/prime-number-algorithms#:~:text=Most%20algorithms%20for%20finding%20prime,test%20or%20Miller%2DRabin%20method。

如果 n 为 1,您的代码将给出错误的答案。

您的时间复杂度可以降低到sqrt(n(,其中n 是数字

这是代码

bool isPrime(long int n)
{
if (n == 1)
{
return false;
}
int i = 2;
while (i*i <= n)
{
if (n % i == 0)
{
return false;
}
i += 1;
}
return true;
}

"long int"将有助于避免溢出。

希望这有帮助。

如果数字不是太大,你也可以尝试使用埃拉托色尼的筛子来解决这个问题:

#include <iostream>
#include <array>
using namespace std;
constexpr int LIMIT = 100001;
// not_prime because global variables are initialized with 0
bool not_prime[LIMIT];
void sieve() {
int i, j;
not_prime[2] = false;
for(int i = 2; i < LIMIT; ++i) 
if(!not_prime[i])
for(int j = i + i; j < LIMIT; j += i) 
not_prime[j] = true;
}
int existaP(int a[], int li, int ls){
if(li==ls)
if(!not_prime[a[li]] == true) 
return 1;
else  
return 0;
else   
return existaP(a, li, (li + ls) / 2) + existaP(a, (li + ls) / 2 + 1, ls);      
}
int main(){
int n, a[10001];
cin >> n;
for(int i = 1; i<=n; ++i) cin >> a[i];
sieve();
if(existaP(a,1,n) >= 1) cout << "Y";
else cout << "N";
return 0;
}

基本上,当你遇到一个素数时,所有数的倍数都不会是素数。

附言:Acum am vazut ca esti roman :) Poti sa te uiti aici pentru a optimiza si mai mult algoritmul: https://infoarena.ro/ciurul-lui-eratostene

另一个尚未提到的低效率是existaP(a, li, (li+ls)/2) + existaP(a, (li+ls)/2+1, ls);

特别是,这里的问题是+.如果你知道existaP(a, li, (li+ls)/2)>0,那么existaP(a, (li+ls)/2+1, ls)就不再重要了。换句话说,您目前正在计算唯一因子的确切数量,但是一旦您知道一个数字至少有两个因子,您就知道它不是素数。

这是检查给定数字是素数的一种有效方法。

bool isprime(int n) {
if(n<=1)
return false;
if(n<=3)
return true;
if(n%2==0||n%3==0)
return false;
for(int i=5;i*i<=n;i=i+6) {
if(n%i==0||n%(i+2)==0)
return false;
}
return true;
}

在我看来,这是一个更快的算法。它适用于欧几里得算法来计算 H.C.F. 基本上,我检查数字和连续第二个数字的 HCF 是否为 1;如果数字本身可以被 2 或 3 整除。不要问我是如何在数学上得出解决方案的,它只是让我:D。该解决方案的时间复杂度为 O(log (max(a,b(((,明显小于运行循环计数器 2 到 sqrt(n( 的程序的时间复杂度为 O(sqrt(n((。

#include <iostream>
using namespace std;

int hcf(int, int);

int hcf(int a, int b)
{
if (b == 0)
{
return a;
}

return hcf(b, a % b);
}

int main()
{
int a;

cout << "nEnter a natural number: ";
cin >> a;

if(a<=0)
{
cout << "nFor conventional reasons we keep the discussion of primes to natural numbers in this program:) (Read: Ring of Integers / Euclid's Lemma)";
return 0;
}

if (a == 1)
{
cout << "nThe number is neither composite nor prime :D";
return 0;
}

if (a == 2)
{
cout << "nThe number is the only even Prime :D";
return 0;
}

if (hcf(a, a + 2) == 1)
{
if (a % 2 != 0 && a % 3 != 0)
{
cout << "nThe number is a Prime :D";
return 0;
}
}

cout << "nThe number is not a Prime D:";

return 0;
}

如果我错了,请纠正我。我是学生。