繁体   English   中英

优化质数代码?

[英]Optimizing prime numbers code?

我写这段代码是为了显示 1 到 100 之间的素数。唯一的条件是不要使用函数,整个代码应该是内联的。 我会问我是否可以进一步改进(优化)它?

#include<iostream>

using namespace std;

int main() {

    int i=2,j=2;

    cout<<"Prime numbers between 1 and 100 are:"<<endl;
    cout<<"2"<<"\t";
    while(i!=100) {
        for(int j=2;j<i;j++) {
            if(i%j==0)
            break;

            if(j==i-1)
            cout<<i<<"\t";
        }

        i++;
    }

    cout<<endl;
    system("pause");
    return 0;
}
    for(int j=2;j<i;j++){

这个不好看。

首先,您只需要检查j <= sqrt(i) ,例如 7 永远不会在没有休息的情况下除以 12。

其次,您应该跟踪所有以前找到的素数; 将它保持在向量中,并且只针对它的内容我写的条件执行此循环。

您可以优化现有代码:

  • 在 while 循环中,您应该有一个步骤 2,这样您就不会测试偶数。
  • 在你的 for 循环中,当你达到你正在测试的数字的平方根时你应该停止

您可以使用不同的方法:

在 Erastoses 的筛子上,只需删除可被 2,3 和 5 整除的数字即可显着减少测试素性所需的次数。

避免使用平方根函数,并将除数增加 2。在 i 循环中还有一些棘手的事情,将可能的素数增加 2。内循环甚至不需要检查 2 的可整性,因为甚至不会测试偶数.

int i,j,sq;
int min;
for(sq = 2; sq <= 10; sq++)
{
  min = (sq-1)*(sq-1);
  min = min + (min+1)%2; //skip if it's even, so we always start on odd
  for(i = min; i < sq*sq; i+=2)
  {
    for(j = 3; j <= sq; j+=2)
    {
      if (i%j == 0)
        bad;
    }
  }
}

请注意, sq 循环不会增加时间,因为它会按比例缩小内部循环。

如果您只想要 100 以下的素数,则无需编写代码来计算它们。 这可能是一个愚蠢的答案,但它可以有效而简洁地解决您的问题。

int main() {
    cout << "Prime numbers are:" << endl << "2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97" << endl;
    return 0;
}

您正在检查从 2 到 100 的每个数字。但由于 2 是唯一的偶数素数,因此您可以跳过 2 之后的每个偶数。这对ij都适用。 所以从 3 开始ij ,并将它们增加 2。

#include<iostream>

using namespace std;

int main() {
    cout<<"Prime numbers between 1 and 100 are:"<<endl;
    cout<<"2"<<"\t";
    for (int i=3; i<100;i+=2) {
        // This loop stops either when j*j>i or when i is divisible by j.
        // The first condition means prime, the second, not prime.
        int j=3;
        for(;j*j<=i && i%j!=0; j+=2); // No loop body

        if (j*j>i) cout << i << "\t";
    }
    cout<<endl;
    return 0;
}

除了上面提到的技巧,我还添加了条件j*j<=i ,它在逻辑上与j<=sqrt(i)完全相同。 当您可以进行简单的乘法运算时,无需计算平方根。

取决于您要进行哪种优化。 你的尽可能好,我可以看到你是否首先优化空间,其次(好吧,关闭 - 只要你听@Paul,它就会)。 如果您颠倒优先级,Erastothenes 的筛选会更快(但会占用您的 100 个布尔值)。

你可以做两个简单的优化:

cout << 2 << '\t';
for (int i = 3; i <= 100; ++i) {
    for (int j = 3, l = (int)sqrt(i); j <= l; j += 2) {
        if (i % j == 0) {
            cout << i << '\t';
            break;
        } 
} 

我做了什么:

数学:

  • j > sqrt(i)时停止,没有必要更进一步。 但是请注意, sqrt是一个昂贵的函数; 对于您的小样本(从 1 到 100),使用它可能(阅读,肯定会)花费更多。
  • 只检查奇数; j += 2而不是一一递增j

微观优化:

  • 使用++i而不是i++ 后者有一个临时变量,用于存储i的原始值; 前者没有。
  • 打印'\\t'作为字符而不是字符串"\\t"

(无论如何,这些微优化可能是由编译器自动进行的,但了解它们并没有什么坏处。)

实现这一目标的最有效方法是埃拉托色尼筛法。 这是一个增量版本,专门用于生成最多100的素数,一个一个(最多120 ,因为121 == 11 * 11 )。

int m3 = 9, m5 = 25, m7 = 49, i = 3;
printf("2 ");
for( ; i < 100; i += 2 )
{
    if( i != m3 && i != m5 && i != m7)
        printf("%d ", i);
    else
    {
        if( i == m3 ) m3 += 6;
        if( i == m5 ) m5 += 10;
        if( i == m7 ) m7 += 14;
    }
}
/*** Return an array of primes from 2 to n. ***/
int[] function nPrimes(int n) {
   int primes[];  //memory allocation may be necessary depending upon language.
   int p = 0;
   bool prime;
   for (int i = 2; i <= n; i++) {
       prime = true;
       //use (j <= (int)sqrt(i)) instead of (j < i) for cost savings.
       for (int j = 2; j <= (int)sqrt(i); j++)  {
           if (i % j == 0) {
               prime = false;
               break;
           }
       }
       if (prime) {
           primes[p++] = i;
       }    
   }
   return primes;
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM