使用筛选法求N以内的素数

1. 使用筛选法求素数的思想是:使用一个bool isPrime[N]来存储一个数是不是素数的标志位。

  首先偶数不是素数(2除外),将2的倍数isPrime全部设置为false。

  i从3开始遍历,如果i为素数,则将i的倍数isPrime全部设置成false。这样就筛选掉了好多不是素数的数。

  从0遍历isPrime[i]数组,如果值为true,则说明i为素数,否则i不是素数。

2. 代码如下:

  

View Code
 1 #include <iostream>
 2 #include <cassert>
 3 #include <cmath>
 4 using namespace std;
 5 
 6 #define N 10000001
 7 bool isPrime[N];
 8 
 9 bool Prime(int n)
10 {
11     if (n<2)
12     {
13         return false;
14     }
15     if (n==2)
16     {
17         return true;
18     }
19     int upper=sqrt(static_cast<double>(n));
20     for (int i=2;i<=upper;i++)
21     {
22         if (n%i==0)
23         {
24             return false;
25         }
26     }
27     return true;
28 }
29 int main()
30 {
31     isPrime[0]=isPrime[1]=false;
32     isPrime[2]=true;
33     int i=2;
34     for (int i=3;i<N;i++)
35     {
36         if ((i&(0x01)) ==0)    //用位运算代替i%2==0
37         {
38             isPrime[i]=false;
39         }
40         else
41         {
42             isPrime[i]=true;
43         }
44     }
45     int upper=sqrt(static_cast<double>(N));
46     for(int i=3;i<upper;i+=2)
47     {
48         if (isPrime[i] && Prime(i))
49         {
50             for (int j=i+i;j<N;j+=i)
51             {
52                 isPrime[j]=false;
53             }
54         }
55     }
56     int count=0;
57     for (int i=0;i<N;i++)
58     {
59         if (isPrime[i])
60         {
61             //cout<<i<<"  ";
62             count++;
63         }
64     }
65     cout<<count<<endl;
66 
67     //最原始的求素数方法,速度很慢
68     //int count=0;
69     //for (int i=2;i<N;i++)
70     //{
71     //    if (Prime(i))
72     //    {
73     //        count++;
74     //    }
75     //}
76     //cout<<count<<endl;
77     return 0;
78 }

3. 代码可以做如下优化:

  1. isPrime数组大小可减少为原来的一半,只存储素数的标志位,不存储偶数的标志位。毕竟偶数都不是质数。

  2. 如果判断一个数是不是素数,可以维护一个很大的素数表,即将一定范围内的素数首先都求出来,存储在数组内,为了节省内存可以使用位图存储。

4. 参考文章:

http://dongxicheng.org/structure/prime/

http://blog.sina.com.cn/s/blog_69c62b650100y53r.html

转载于:https://www.cnblogs.com/ZJUKasuosuo/archive/2012/08/08/2628360.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值