2011-11-02 60 views
2

可能重复:
Which is the fastest algorithm to find prime numbers?打印素数小于100

有没有什么办法,使这更优化..

#include <vector> 
    int main() 
    { 
     std::vector<int> primes; 
     primes.push_back(2); 
     for(int i=3; i < 100; i++) 
     { 
      bool prime=true; 
      for(int j=0;j<primes.size() && primes[j]*primes[j] <= i;j++) 
      { 
       if(i % primes[j] == 0) 
       { 
        prime=false; 
        break; 
       } 
      } 
      if(prime) 
      { 
       primes.push_back(i); 
       cout << i << " "; 
      } 
     } 

     return 0; 
    } 
+2

你可以你的循环i ++在部分变为I + = 2,因为我们知道所有的连号都不会是首要反正 – Akron

+0

你需要添加作业标签? –

+0

已经有很多关于此主题的SO问题。 – mydogisbox

回答

4

Sieve of Eratosthenes是一个伟大的算法用于产生一定数量的素数(这不是你的标题所指出的,b你的代码暗示了什么)。

+0

我不认为Sieve算法在[1..100]内的数字的情况下比nave算法效果更好 –

+0

@SaeedAmiri任何你不认为这个的原因? –

+0

@PaŭloEbermann,因为在这个范围内有很多可以分割为2,3,5,7的数字,你会多次检查它们,但是通过nave算法,你可以跳过这种类型的检查,因为只有3,5个, 7应该在nave算法中检查,实际上最多只有150个检查,性能问题并不多,但在筛选算法中,我不知道应该有多少检查,但应该超过150个,这只是猜测计算它并不困难。 –

1

是的,将i++更改为i+=2,它的工作速度会提高一倍。

+0

不,它不会......只是微观优化 –

+0

如果你只测试一半的数字,为什么它不会让它快一倍? –

+0

,因为您是针对第一个素数进行测试,即2,立即退出循环。 –

11
int main(int argc, char *argv[]) { 
    cout << "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 "; 
} 

:-)

更严重的是,你能避免缓存primes[j] * primes[j]反复平方素数,节省乘法。

+0

101,你忘了! –

+0

+1:给定范围的一个很好的答案。 –

+0

哈哈,我喜欢这个回应。这是真正的最快的方式输出所有素数低于100 – Akron

2
  1. 不做primes[j]*primes[j] <= i只是检查primes[j] <= 7
  2. 使用i+=2
+0

考虑到'primes [3] == 7',写'j <= 3'更简单。 (primes [j] <11'会更明显)。 – MSalters

1

是。正如Marion所建议的那样,您可以使用Sieve of Eratosthenes,但您应该了解详细信息。你写的代码看起来像筛子,但事实并非如此。它被称为审判分裂,它有不同于筛子的algorithmic complexity

筛子执行每个素数p需要Theta(n/p)时间的合格。这导致总复杂度为O(n log log n)。 IIRC证明有点复杂,涉及prime number theorem

您的算法对每个素数p执行pi(sqrt(p))除法,对于非素数执行较小数目的除法。 (其中piprime-counting function)。不幸的是,我无法想出完全的复杂性。

简而言之,您应该更改代码以使用数组并标记所有非素数。 This article解决了函数式编程语言中的相同主题。

+0

是的。我显然没有想到它通过。 –

1

是的,Eratosthenes筛是最好​​的选择(如果你需要100个以上的号码this是最好的实施)。这是我的实现:

#include <vector> 
#include <iostream> 
#include <cmath> 
using namespace std; 

vector<int> sieve(int n){ 
    vector<bool> prime(n+1,true); 
    vector<int> res; 
    prime[0]=prime[1]=false; 
    int m = (int)sqrt(n); 
    for(int i=2; i<=m; i++){ 
     if(prime[i]) 
      for(int k=i*i; k<=n; k+=i) 
       prime[k]=false; 
    } 
    for(int i=0; i<n ;i++) 
     if(prime[i]) 
      res.push_back(i); 
    return res; 
} 

int main(){ 
    vector<int> primes = sieve(100); 
    for(int i=0; i<primes.size() ;i++){ 
     if(i) cout<<", "; 
     if(primes[i]) cout<<i; 
    } 
    cout<<endl; 
} 
+0

一个有趣的问题是,使用'vector '是否比使用'vector '要快(0和1为false和true)。 'vector '当然需要额外的努力才能读取或写入任何单个值,但'vector '会占用8倍以上的内存,减少了局部性,并导致更多的缓存未命中。 –

+0

在C++布尔和字符中使用8位,但布尔不使用所有这些。 – vudduu

+0

在C++中,“bool”或“c​​har”的大小是实现定义的。我知道今天的机器,其中'char'是8,9或32位,'bool'可以是单个'char',或者更多---肯定有系统,它的大小与int '(4或6个字节,在两个平台上我知道这是这种情况)。这里没有一个是相关的,因为'std :: vector '专门用于每个布尔值只使用1位。我的评论从哪里来。 –