筛素数法小结

简介:

筛选素数方法小结:

  最简单的筛素数法方法就是从2开始,将所以2的倍数去掉,然后从3开始,将3的倍数去掉,依次进行下去即可。根据这样很容易写出代码,下面代码就是是筛素数法得到100以内的素数并保存到primes[]数组中。

复制代码
复制代码
 1 const int MAXN = 100;
 2 bool flag[MAXN];
 3 int primes[MAXN / 3], pi;
 4 void GetPrime_1()
 5 {
 6     int i, j;
 7     pi = 0;
 8     memset(flag, false, sizeof(flag));
 9     for (i = 2; i < MAXN; i++)
10         if (!flag[i])
11         {
12             primes[pi++] = i;
13             for (j = i; j < MAXN; j += i)  //剔除待考察数据j的倍数,并置其flag位为true
14                 flag[j] = true;
15         }
16 }
复制代码
复制代码

  可以看出这种会有很多重复访问,如在访问flag[2]和flag[5]时会各访问flag[10]一次。因此最好想方法来减少这种重复访问,让flag[]数组的每个元素只被访问一次。可以这样考虑——简单的筛素数法是利用一个素数的倍数必须不是素数,同样任何一个数与其它所有素数的乘积必然也不是素数(这是因为每个合数必有一个最小素因子)。

      为了试验这种想法,先用2到10之间的数来验证下。

      2,3,4,5,6,7,8,9,10      初始时所以flag都是无标记的。

  第一步 访问2,flag[2]无标记所以将2加入素数表中,然后将2与素数表中的所有数相乘得到的数必定不是素数,2*2=4因此标记flag[4]。

   2,3,4,5,6,7,8,9,10

  第二步 访问3,flag[3]无标记所以将3加入素数表中,将3与素数表中的所有数相乘得到的数必定不是素数,3*2=6,3*3=9因此标记flag[6]和flag[9]。

   2,3,4,5,6,7,8,9,10

  第三步 访问4,flag[4]有标记所以4不加入素数表中,将4与素数表中的所有数相乘得到的数必定不是素数, 4*2=8,4*3=12因此标记flag[8]。

   2,3,4,5,6,7,8,9,10

  第四步 访问5,flag[5]无标记所以将5加入素数表中,将5与素数表中的所有数相乘得到的数必定不是素数,5*2=10,5*3=15因此标记flag[10]。

   2,3,4,5,6,7,8,9,10

  第五步 访问6,flag[6]有标记所以6不加入素数表中,将6与素数表中的所有数相乘得到的数必定不是素数, 6*2=12,6*3=18,6*5=30。

   2,3,4,5,6,7,8,9,10

    后面几步类似,具体代码如下:

复制代码
复制代码
 1 const int MAXN = 100;
 2 bool flag[MAXN];
 3 int primes[MAXN / 3], pi;
 4 void GetPrime_2()
 5 {
 6     int i, j;
 7     pi = 0;
 8     memset(flag, false, sizeof(flag));
 9     for (i = 2; i < MAXN; i++)
10     {
11         if (!flag[i])
12             primes[pi++] = i;  //flag未标记为true,将其加入到素数表中
13         for (j = 0; (j < pi)  && (i * primes[j] < MAXN); j++)  //依次剔除待考察数据与素数表中数据的乘积,并置其flag位为true
14             flag[i * primes[j]] = true;
15     }
16 }
复制代码
复制代码

  这份代码对不对呢?仔细回顾下分析过程,可以发现有些数据还是被访问了多次,这当然不是我们希望的结果,我们的要求是让每个合数仅被它的最小素因子筛去一次。比如12,它的最小素因子是2,所以就只应该被在计算6*2时去访问,而且不应该在计算4*3时去访问,同理18也只应该被在计算9*2时去访问,而且不应该在计算6*3时去访问。

    找到原因后,再来思考如何解决。6*3不行而9*2可以了,是因为6是2的倍数,所以在计算6*2之后就不能再将6与比2大的素数相乘,这些相乘的结果必定会导致重复计算。因此对于任何数来说,如果它是该素数的倍数那么它就不能再与素数表中该素数之后的素数相乘了,如9是3的倍数,所以在9*3之后就不能再去用计算9*5了。因此在代码中再增加一行判断语句:

复制代码
复制代码
 1 const int MAXN = 100;
 2 bool flag[MAXN];
 3 int primes[MAXN / 3], pi;
 4 void GetPrime_2()
 5 {
 6     int i, j;
 7     pi = 0;
 8     memset(flag, false, sizeof(flag));
 9     for (i = 2; i < MAXN; i++)
10     {
11         if (!flag[i])
12             primes[pi++] = i;
13         for (j = 0; (j < pi)  && (i * primes[j] < MAXN); j++)
14         {
15             flag[i * primes[j]] = true;
16             if (i % primes[j] == 0) //这句保证每个非素数只被筛去一次
17                 break;
18 }
19     }
20 }
复制代码
复制代码

  想知道这二种筛素数法方法的区别吗?现在对求2到1亿之间的素数进行测试,看看区别到底会有多大,测试代码如下:

复制代码
复制代码
 1 /*
 2 *描述:筛素数法(倍数剔除、最小素因子筛选)对比
 3 *分析:倍数剔除:一个素数的倍数必须不是素数,即从2开始,将所以2的倍数去掉,然后从3开始,将3的倍数去掉,依次进行下去即可
 4 *       最小素因子筛选:简单的筛素数法(倍数剔除)是利用一个素数的倍数必须不是素数,同样任何一个数与其它所有素数的乘积必然也不是素数(这是因为每个合数必有一个最小素因子)。
 5                        要求是让每个合数仅被它的最小素因子筛去一次;即如果它是该素数的倍数那么它就不能再与素数表中该素数之后的素数相乘了。
 6 *
 7 *
 8 */
 9 #include <stdio.h>
10 #include <stdlib.h>
11 #include <memory.h>
12 #include <time.h>
13 #include <math.h>
14 const int MAXN = 100000000;
15 bool flag[MAXN];
16 int primes[MAXN / 3], pi;
17 // 利用对每个素数的倍数必定不是素数来筛选
18 void GetPrime_1()
19 {
20     int i, j;
21     pi = 0;
22     memset(flag, false, sizeof(flag));
23     for (i = 2; i < MAXN; i++)
24         if (!flag[i])
25         {
26             primes[pi++] = i;
27             for (j = i; j < MAXN; j += i)
28                 flag[j] = true;
29         }
30 }
31 // 利用了每个合数必有一个最小素因子来筛选
32 void GetPrime_2()
33 {
34     int i, j;
35     pi = 0;
36     memset(flag, false, sizeof(flag));
37     for (i = 2; i < MAXN; i++)
38     {
39         if (!flag[i])
40             primes[pi++] = i;
41         for (j = 0; (j < pi)  && (i * primes[j] < MAXN); j++)
42         {
43             flag[i * primes[j]] = true;
44             if (i % primes[j] == 0)
45                 break;
46         }
47     }
48 }
49 int main()
50 {
51     printf(" 在%d的数据量下普通的筛素数方法与改进之后的效率对比\n", MAXN);
52     clock_t clockBegin, clockEnd;
53     
54     clockBegin = clock();
55     GetPrime_1();
56     clockEnd = clock();
57     printf("普通的筛素数方法\t%d毫秒\n", clockEnd - clockBegin);
58     
59     clockBegin = clock();
60     GetPrime_2();
61     clockEnd = clock();
62     printf("改进的筛素数方法\t%d毫秒\n", clockEnd - clockBegin);
63     system("pause");
64     return 0;
65 }
复制代码
复制代码

具体的运行结果如下:

 

总结:

  1.普通的筛素数的原理是一个素数的倍数必须不是素数。

  2.改进的筛素数的原理是每个合数必有一个最小素因子,根据每个最小素因子去访问合数就能防止合数被重复访问。

我是天王盖地虎的分割线                                                                     

 

 

参考:http://www.cnblogs.com/xymqx/p/3718276.html

 

作者: 我爱物联网 
出处: http://yydcdut.cnblogs.com/ 
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。



本文转自我爱物联网博客园博客,原文链接:http://www.cnblogs.com/yydcdut/p/3876195.html,如需转载请自行联系原作者
相关文章
|
16小时前
|
存储 关系型数据库 MySQL
数据管理的艺术:PolarDB开源版详评与实战部署策略(一)
PolarDB-X是阿里巴巴自研的高性能云原生分布式数据库,基于共享存储的Shared-nothing架构,支持MySQL生态,具备金融级高可用、分布式水平扩展、HTAP混合负载等能力。它通过CN(计算节点)和DN(存储节点)实现计算与存储分离,保证数据强一致性,并支持全局二级索引和多主多写。PolarDB-X开源版提供更高程度的定制化和控制权,适合追求技术自主性和成本优化的开发者。部署方式包括RPM包、PXD工具和Kubernetes,其中PXD工具提供了一键部署的便利性。
31515 10
|
4天前
|
关系型数据库 Serverless 分布式数据库
高峰无忧,探索PolarDB PG版Serverless的弹性魅力
在数字经济时代,数据库成为企业命脉,面对爆炸式增长的数据,企业面临管理挑战。云原生和Serverless技术革新数据库领域,PolarDB PG Serverless作为阿里云的云原生数据库解决方案,融合Serverless与PostgreSQL,实现自动弹性扩展,按需计费,降低运维成本。它通过计算与存储分离技术,提供高可用性、灾备策略和简化运维。PolarDB PG Serverless智能应变业务峰值,实时监控与调整资源,确保性能稳定。通过免费体验,用户可观察其弹性性能和价格力,感受技术优势。
|
14天前
|
存储 缓存 监控
你的Redis真的变慢了吗?性能优化如何做
本文先讲述了Redis变慢的判别方法,后面讲述了如何提升性能。
102215 3
|
14天前
|
机器学习/深度学习 并行计算 算法
Transformer 一起动手编码学原理
学习Transformer,快来跟着作者动手写一个。
94245 7
|
13天前
|
存储 SQL Apache
阿里云数据库内核 Apache Doris 基于 Workload Group 的负载隔离能力解读
阿里云数据库内核 Apache Doris 基于 Workload Group 的负载隔离能力解读
阿里云数据库内核 Apache Doris 基于 Workload Group 的负载隔离能力解读
|
19天前
|
人工智能 弹性计算 算法
一文解读:阿里云AI基础设施的演进与挑战
对于如何更好地释放云上性能助力AIGC应用创新?“阿里云弹性计算为云上客户提供了ECS GPU DeepGPU增强工具包,帮助用户在云上高效地构建AI训练和AI推理基础设施,从而提高算力利用效率。”李鹏介绍到。目前,阿里云ECS DeepGPU已经帮助众多客户实现性能的大幅提升。其中,LLM微调训练场景下性能最高可提升80%,Stable Difussion推理场景下性能最高可提升60%。
123947 21
|
14天前
|
存储 弹性计算 Cloud Native
1 名工程师轻松管理 20 个工作流,创业企业用 Serverless 让数据处理流程提效
为应对挑战,语势科技采用云工作流CloudFlow和函数计算FC,实现数据处理流程的高效管理与弹性伸缩,提升整体研发效能。
64734 2
|
20天前
|
消息中间件 安全 API
Apache RocketMQ ACL 2.0 全新升级
RocketMQ ACL 2.0 不管是在模型设计、可扩展性方面,还是安全性和性能方面都进行了全新的升级。旨在能够为用户提供精细化的访问控制,同时,简化权限的配置流程。欢迎大家尝试体验新版本,并应用在生产环境中。
187514 11
|
16天前
|
存储 关系型数据库 数据库
|
24天前
|
物联网 PyTorch 测试技术
手把手教你捏一个自己的Agent
Modelscope AgentFabric是一个基于ModelScope-Agent的交互式智能体应用,用于方便地创建针对各种现实应用量身定制智能体,目前已经在生产级别落地。