筛素数法小结

简介:

筛选素数方法小结:

  最简单的筛素数法方法就是从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,如需转载请自行联系原作者
相关文章
|
数据挖掘
深入分析:ERP系统的优势与劣势
深入分析:ERP系统的优势与劣势
918 3
|
机器学习/深度学习 弹性计算 运维
阿里云轻量应用服务器和云服务器ECS区别(终于懂了)
阿里云轻量应用服务器和云服务器ECS区别(终于懂了)阿里云服务器ECS和轻量应用服务器有什么区别?云服务器ECS是明星级云服务器,轻量应用服务器可以理解为简化版的云服务器ECS,轻量适用于单机应用,云服务器ECS适用于集群类高可用高容灾应用,阿里云百科来详细说下阿里云轻量应用服务器和云服务器的区别
2082 0
|
人工智能
AI与艺术:数字时代的新文艺复兴
本文探讨了人工智能在艺术创作中的应用及其对传统艺术观念的挑战。通过分析AI技术如何改变艺术创作的流程和审美标准,文章揭示了这一技术革新如何引发文化领域的深刻变革。
|
10月前
|
存储 数据可视化 定位技术
如何高效管理远程团队?2024年最佳免费工作协作工具排行榜
随着远程工作日益普遍,选择合适的协作工具成为提升团队效率的关键。本文介绍了7款优秀的免费远程协作工具,包括板栗看板、Wrike、Miro、ClickUp、Zoho Projects、MeisterTask和Quire,它们各自具备独特优势,如项目管理、任务跟踪、文件共享及实时协作等功能,适用于不同规模和需求的团队,帮助实现高效远程工作。
如何高效管理远程团队?2024年最佳免费工作协作工具排行榜
|
12月前
|
网络协议 物联网 5G
探索未来网络:IPv6的演进与应用
本文深入探讨了互联网协议第六版(IPv6)的发展背景、技术特性及其在现代网络中的应用。通过分析IPv4面临的地址枯竭问题,阐述了IPv6作为解决方案的重要性和紧迫性。文章详细介绍了IPv6相较于IPv4的改进之处,如更大的地址空间、简化的包头格式、增强的组播支持等,并探讨了IPv6在实际部署中遇到的挑战及应对策略。通过对IPv6过渡技术和双栈技术的讨论,揭示了其在促进下一代互联网发展中的关键作用。此外,文章还展望了IPv6在未来网络安全、物联网整合以及新兴技术中的应用前景,强调了掌握IPv6技术对于把握未来互联网发展趋势的重要性。
207 11
|
11月前
|
存储 测试技术
ECCV 2024:比基准高30%,媲美Gemini 1.5 Pro,基于记忆的视频理解智能体来了
在ECCV 2024会议上,一篇题为“VideoAgent: A Memory-augmented Multimodal Agent for Video Understanding”的论文备受关注。该论文提出了一种结合大型语言模型和视觉-语言模型的新型智能体VideoAgent,通过创新的统一记忆机制,构建结构化记忆系统,实现对长视频中时间关系的理解。VideoAgent利用视频片段定位、物体记忆等多种工具进行交互式任务处理,在NExT-QA和EgoSchema等基准测试中表现出色,分别提升了6.6%和26.0%的成绩,但其记忆系统和交互方法仍有待优化。
200 1
|
10月前
|
API 数据处理 开发工具
云计算在金融行业的应用与挑战
云计算在金融行业的应用与挑战
633 0
|
11月前
|
人工智能 数据可视化 数据挖掘
5款CRM系统评测:中小企业如何选择适合的CRM工具?
在竞争激烈的市场中,中小企业如何高效管理客户关系、提升销售业绩、改善客户满意度是其成功的关键。本文评测了5款主流CRM系统,分别为板栗看板、HubSpot CRM、Zoho CRM、Pipedrive和Salesforce Essentials,从功能特色、优缺点及使用体验等角度进行分析,帮助中小企业选择最适合的工具。
313 0
|
JavaScript 前端开发 索引
vue 实现任务步骤条
vue 实现任务步骤条
382 0
|
人工智能 算法 数据挖掘
什么是程序设计
一、什么是程序设计 程序设计是指通过编写、测试和维护计算机程序来解决问题或实现特定功能的过程。它涉及到确定问题的需求、设计算法、选择合适的编程语言、编写代码、调试和测试程序等步骤。程序设计的目标是创建高效、可靠、易于理解和维护的软件。 二、程序设计具有以下特点 1. 抽象性:程序设计是一种高度抽象的活动,它涉及到将实际问题转化为计算机可以理解和执行的指令。 2. 逻辑性:程序设计需要遵循严格的逻辑结构和规则,以确保程序的正确性和可靠性。逻辑思维和分析能力是程序设计的重要组成部分。 3. 创造性:程序设计是一种创造性的活动,程序员需要在解决问题的过程中提出新的思路和方法,以实现更好的效果。
897 0