用C++实现的增强Eratosthenes筛法程序
运行示例
PS H:\Read\num\x64\Release> .\eSievePro
Eratosthenes sieve: a method to find out all primes below the number that you specify here please: 100
Only the sum of all primes needed [y/n](y as default): n
Start to work out all primes below 100...
25 primes found in 0 milliseconds.
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
PS H:\Read\num\x64\Release> .\eSievePro
Eratosthenes sieve: a method to find out all primes below the number that you specify here please: 12345678
Only the sum of all primes needed [y/n](y as default):
Start to work out the sum of all primes below 12345678...
809227 primes found in 63 milliseconds.
PS H:\Read\num\x64\Release> .\eSievePro
Eratosthenes sieve: a method to find out all primes below the number that you specify here please: 123456789
Only the sum of all primes needed [y/n](y as default):
Start to work out the sum of all primes below 123456789...
7027260 primes found in 1031 milliseconds.
PS H:\Read\num\x64\Release> .\eSievePro
Eratosthenes sieve: a method to find out all primes below the number that you specify here please: 1234567890
Only the sum of all primes needed [y/n](y as default):
Start to work out the sum of all primes below 1234567890...
62106578 primes found in 12375 milliseconds.
PS H:\Read\num\x64\Release> .\eSievePro
Eratosthenes sieve: a method to find out all primes below the number that you specify here please: 1234567
Only the sum of all primes needed [y/n](y as default):
Start to work out the sum of all primes below 1234567...
95360 primes found in 0 milliseconds.
PS H:\Read\num\x64\Release>
和用C++实现的Eratosthenes筛法程序对比,性能有显著提升。
增强Eratosthenes筛法的C++程序实现
为说明方便,把用C++实现的Eratosthenes筛法程序里的实现称为eSieve,而把这里的新实现称为eSievePro。
宏定义和全局量定义
1 typedef unsigned char u8;
2 typedef unsigned long ulong;
3 static ulong s_last = 0;
4 static u8* s_pOdd = NULL;
5 static std::vector<ulong> s_vecPrime;
对照eSieve的相应部分,这里只是把之前的s_pAll换成了s_pOdd。
main函数实现
1 int main()
2 {
3 printf(" Eratosthenes sieve: a method to find out all primes below the number that you specify here please: ");
4 std::string strInput;
5 getline(std::cin, strInput);
6 ulong raw_last = strtoul(strInput.c_str(), 0, 10);
7 if (raw_last <= 2) {
8 printf("\n Wrong input.\n");
9 return 0;
10 }
11 printf("\n Only the sum of all primes needed [y/n](y as default): ");
12 getline(std::cin, strInput);
13 bool bDetail = (strInput == "n");
14 if (bDetail)
15 printf("\n Start to work out all primes below %u...\n", raw_last);
16 else
17 printf("\n Start to work out the sum of all primes below %u...\n", raw_last);
18 if (!eSievePro(raw_last, bDetail))
19 return 0;
20 if (bDetail)
21 showDetails();
22 return 0;
23 }
这里的main函数实现保留了交互输入的实现代码,而把增强的Eratosthenes筛法实现放到了单独的eSievePro函数里。
eSievePro函数实现
1 bool eSievePro(ulong raw_last, bool bDetail)
2 {
3 DWORD tickBegin = GetTickCount();
4 s_last = raw_last / 2;
5 s_pOdd = new u8[s_last];
6 if (!s_pOdd) {
7 printf("Lack of memory.\n");
8 return false;
9 }
10 ulong sum = 1;
11 ulong curPrime = 2;
12 if (bDetail)
13 s_vecPrime.push_back(curPrime);
14 if (raw_last == 3)
15 goto Ending;
16
17 memset(s_pOdd, 1, s_last);
18 ulong curPrimeIdx = 0;
19 while (true) {
20 renewCurrentPrime(curPrimeIdx);
21 ++sum;
22 curPrime = (curPrimeIdx + curPrimeIdx) + 1;
23 if (bDetail)
24 s_vecPrime.push_back(curPrime);
25 s_pOdd[curPrimeIdx - 1] = 0;
26 ulong sqr = curPrime * curPrime;
27 if (sqr > raw_last)
28 break;
29 ulong step = curPrime + curPrime;
30 for (ulong idx = sqr; idx < raw_last; idx += step) {
31 s_pOdd[(idx - 1) / 2 - 1] = 0;
32 }
33 }
34 /// pick up all the left primes
35 for (ulong idx = curPrime + 2; idx < raw_last; idx += 2) {
36 ulong halfIdx = (idx - 1) / 2 - 1;
37 if (s_pOdd[halfIdx] == 1) {
38 ++sum;
39 if (bDetail)
40 s_vecPrime.push_back(idx);
41 }
42 }
43
44 Ending:
45 printf(" %u primes found in %u milliseconds.\n\n", sum, GetTickCount() - tickBegin);
46 delete []s_pOdd;
47 return true;
48 }
由
4 s_last = raw_last / 2;
5 s_pOdd = new u8[s_last];
这两行代码可以看出,s_pOdd的动态申请的空间是原来的一半,就是说原来的动态数组s_pAll记录的是1、2、3、……、upperLimit(upperLimit指代交互输入的上界值)所有自然数的素合状态(1表示素数,0表示合数);而这里的动态数组s_pOdd只用一半的空间来记录1到upperLimit之内的所有奇数的素合状态。这样处理不但节省了存储空间,而且直接省去了Eratosthenes筛法中用2筛去所有偶数的处理过程。
如下这几行筛法实现代码
26 ulong sqr = curPrime * curPrime;
29 ulong step = curPrime + curPrime;
30 for (ulong idx = sqr; idx < raw_last; idx += step) {
31 s_pOdd[(idx - 1) / 2 - 1] = 0;
32 }
相比之前的实现代码
36 for (int idx = curPrime - 1; idx <= s_last - 1; idx += curPrime) {
37 s_pAll[idx] = 0;
38 }
有两个改进之处。用一个实例说明一下:比如用Eratosthenes筛法筛去1到1000之内的合数,依次筛去2的倍数、3的倍数、5的倍数、7的倍数,当开始筛去11的倍数时,会依次筛去22、33、44、55、66、77、88、99、110、121、132、143、……,但是22、33、44、55、66、77、88、99、110这些数因为小于11*11,必然有小于11的素因素,说明这些数必然会在此前筛去2、3、5、7等素数的倍数的过程中被筛掉,因此当筛去一个素数的倍数时,从该素数的平方为起点开始筛会减少重复,在上面的代码对比上用标黄部分表示。
另一个改进之处,在上面的代码对比上用标蓝部分表示。仍沿用刚才的实例说明,当从121开始筛去11的倍数时,会依次筛去121、132、143、154、165、176、187、……,从这个列表可以看出奇数偶数交替出现,这也很好解释,因为筛法当前用到的素数(curPrime)是一个奇数,设为2n+1,它的平方也是奇数(即4nn+4n+1),再加上2n+1就会变成偶数(即4nn+6n+2),再加上2n+1又会变成奇数(4nn+8n+3),……。因为这些偶数在最早筛去2的倍数时就已经被筛去了,而且2之后的素数都是奇数,所以可以把2之后的筛法步长调整为当时使用素数的两倍,这样性能可以提升一倍。
当然,上述两个改进之处并不能彻底避免多次重复筛去一个合数的问题。比如,刚才的实例中使用步长22会依次筛去121、143、165、187,但是里面的165=11*5*3,在之前已经被3筛去过一次,又被5筛去过一次。
renewCurrentPrime和showDetails
1 bool renewCurrentPrime(ulong& primeIdx)
2 {
3 while (primeIdx < s_last) {
4 ++primeIdx;
5 if (s_pOdd[primeIdx - 1] == 1)
6 return true;
7 }
8 return false;
9 }
这里的renewCurrentPrime和eSieve实现的renewCurrentPrime几乎一样,只是因为s_last和输入参数的含义有变化以及s_pOdd与此前的的s_pAll的不同含义而有些微不同。
showDetails的实现则完全没有变动,这里不再重复放了。
其他
https://github.com/readalps/eSievePro上放了eSievePro实现的源码文件,以及一个运行结果文件。
用C++实现的增强Eratosthenes筛法程序的更多相关文章
- 用C++实现的增强Euler筛法程序
运行示例 PS H:\Read\num\x64\Release> .\eulerSievePro EulerSievePro: a method to find out all primes b ...
- 用C++实现的Eratosthenes筛法程序
运行示例 只输出素数总数的运行示例 PS H:\Read\num\x64\Release> .\esieve.exe Eratosthenes sieve: a method to find o ...
- 用C++实现的Euler筛法程序
Euler筛法介绍 以筛出100以内(含100)的所有素数为例来说明一下欧拉筛法的原理. 和Eratosthenes筛法一样,Euler筛法也从2开始筛,但Eratosthenes筛法会把2的倍数一批 ...
- C语言程序设计100例之(12):Eratosthenes筛法求质数
例12 Eratosthenes筛法求质数 问题描述 Eratosthenes筛法的基本思想是:把某范围内的自然数从小到大依次排列好.宣布1不是质数,把它去掉:然后从余下的数中取出最小的数,宣布它 ...
- 由Eratosthenes筛法演变出的一种素数新筛法
这两天和walls老师交流讨论了一个中学竞赛题,我把原题稍作增强和变形,得到如下一个题: 从105到204这100个数中至少要选取多少个数才能保证选出的数中必有两个不是互素的? 我们知道最小的几个素数 ...
- 25个增强iOS应用程序性能的提示和技巧(高级篇)(2)
25个增强iOS应用程序性能的提示和技巧(高级篇)(2) 2013-04-16 14:56 破船之家 beyondvincent 字号:T | T 在开发iOS应用程序时,让程序具有良好的性能是非常关 ...
- 25个增强iOS应用程序性能的提示和技巧(高级篇)(1)
25个增强iOS应用程序性能的提示和技巧(高级篇)(1) 2013-04-16 14:56 破船之家 beyondvincent 字号:T | T 在开发iOS应用程序时,让程序具有良好的性能是非常关 ...
- 25个增强iOS应用程序性能的提示和技巧(中级篇)(3)
25个增强iOS应用程序性能的提示和技巧(中级篇)(3) 2013-04-16 14:42 破船之家 beyondvincent 字号:T | T 本文收集了25个关于可以提升程序性能的提示和技巧,分 ...
- 25个增强iOS应用程序性能的提示和技巧(中级篇)(2)
25个增强iOS应用程序性能的提示和技巧(中级篇)(2) 2013-04-16 14:42 破船之家 beyondvincent 字号:T | T 本文收集了25个关于可以提升程序性能的提示和技巧,分 ...
随机推荐
- AT2304 Cleaning
AT2304 Cleaning 题意 一个树上每个节点有一些石子,每次只能选取两个叶子节点并将路径间的所有点上的石子数量减1,问是否能将所有石子取完. 思路 设 \(f_x\) 表示从 \(x\) 节 ...
- Springboot通过过滤器实现对请求头的修改
之前在一个项目中有一个API服务需要重构,尤其是接口的用户身份校验,原先的实现是将用户token放在URL请求参数中,然后通过AOP进行校验,现在要统一将token放在header中,但是这样修改会让 ...
- Axure RP 9 Enterprise/Pro/Team for Mac/Windows安装破解版激活教程
Axure RP 9.0 是一款功能强大的.操作方便.专业可靠的快速原型设计工具.一款能够在这里体验最简单的设计方式,这里有着全新的升级的软件界面,更加的时尚,更加的丰富,专为每一个用户提供了便捷的设 ...
- (JAVA1)学习,复习的好帮手
学习准备:博客 博客,英文名Blog,它的正式名称为网络日记. 为什么要写博客 我们学习任何东西都需要总结和思考.有时候我们一直在赶路,却忘了放慢脚步 提升文笔组织能力 提升学习总结能力 提升逻辑思维 ...
- 深入刨析tomcat 之---第9篇 how tomcat works 第9章,Session的实现 关于request.setContext(context)
writedby 张艳涛,在学第9章session的时候,做了个实验在给的demo代码中添加了 package com.zyt.tomcat.ex09.core; public class Simpl ...
- 【阿菜用工具】Slither:Solidity静态分析框架
工具简介 Slither 是一个 python3 开发,用于检测智能合约(solidity)漏洞的静态分析框架. Slither 的 Github 地址:https://github.com/cryt ...
- solr(CVE-2017-12629)远程命令执行
影响版本Apache Solr 5.5.0到7.0.1版本 solr(CVE-2017-12629-RCE) 环境搭建 1.burp检测 创建listen POST /solr/demo/config ...
- (原创)[.Net] 进程间通信框架(基于共享内存)——SimpleMMF
一.前言 进程间通信技术的应用非常广泛,在Windows下常用的实现方式有:管道.Socket.消息.本地文件.共享内存等,每种方式都有各自适应的场景. 在进行大数据交换时,最优的方式便是共享内存. ...
- 【python与机器学习实战】感知机和支持向量机学习笔记(一)
对<Python与机器学习实战>一书阅读的记录,对于一些难以理解的地方查阅了资料辅以理解并补充和记录,重新梳理一下感知机和SVM的算法原理,加深记忆. 1.感知机 感知机的基本概念 感知机 ...
- 音视频开发之H.264 入门知识
大家如果有做过音视频相关的项目,那么肯定对 H.264 相关的概念了解的比较通透,这里我为什么还要写这样一篇文章呢?一来是为了对知识的总结,二来是为了给刚入门音视频的同学一个参考. 基础概念 H.26 ...