用素数筛查找小于等于某个给定整数的全部素数,是一种较为高效的方法,具体的原理网上很多,这里就不赘述了。

但即使都是运用的素数筛原理,不同的算法设计,也可以带来巨大的效率差异。最近从网上搜索学习了相关的原理,验证相关的算法,顺便测试、完善了相关的C++代码,在这里贴出来,分享给有兴趣的读者。

以下两段代码,都可以计算查找9223372036854775807(9百万万亿)内的所有素数。

第一段代码的效率中等,但算法简单易理解。第二段代码据说是目前地球上发现的最高效的方法,但逻辑稍复杂,理解起来有些难度。

这两段代码我均在gcc version 9.2.0+unbutun 20.04 linux上测试通过。

使用第一种算法,在一台2核(CPU主频1.5GHz)+8GB内存的虚拟机(最小化模式安装unbutun 20.04操作系统)上计算查找十亿以内的所有素数,耗时15秒;在同样的硬件水平下,第二种算法耗时80毫秒,显然效率高很多。用第二种算法查找计算千亿范围内的全部素数,耗时4024毫秒;查找计算万亿范围内的全部素数,则耗时毫秒39秒,效率确实比第一种算法高很多。

当计算大量的素数时,需要大量的内存来保存所找到的素数。第一种算法使用动态数组来保存搜索到的素数,第二种算法在这方面的处理更为精准,细化。注意,如果你的计算机内存不大,建议不要尝试去计算超过万亿范围的素数。

第一种算法代码:

/*---------------------------------------------------------------------------------------功能:查找输出所有小于指定值的素数,上限是输出小于等于9223372036854775807的全部质数,并输出保存到CSV文件
---------------------------------------------------------------------------------------*/
#include <bits/stdc++.h>
#include <iostream>
#include <fstream>
#include <vector>
using namespace std;//long long型对应的最大整数为9223372036854775807
#define ll long long//CalPrime函数计算列出小于等于MaxInt的所有素数,并把找到的素数保存到PrimeList数组
void CalPrime(ll MaxInt,ll &CntPrime,ll PrimeList[])
{//MaxInt 要查找素数的范围上限;//CntPrime 小于等于MaxInt的素数个数(不包含1);//PrimeList 找到的素数存储到这个数组列表;ll i,j;clock_t start, end;bool *valid=new bool[MaxInt];CntPrime=0;//开始计算,获取当前系统时间,以便计算结束时统计耗时start = clock();for(i=2; i<=MaxInt; i++)    //将要查找素数范围内的valid全部赋值为true;valid[i]=true;for(i=2; i<=MaxInt; i++){if(valid[i]){if(MaxInt/i<i)break;for(j=i*i; j<=MaxInt; j+=i)    //将不是素数的数所对应的valid[i]赋值为false;valid[j]=false;}}//将[2至MaxInt]范围内的所有素数存入PrimeList数组中;for(i=2; i<=MaxInt; i++){if(valid[i])PrimeList[CntPrime++]=i;}delete valid;   //释放bool数组,回收内存//显示计算所用的时间,我计算999999999(9亿)内的素数,发现有50847534个,计算用时[15391.218000]毫秒//这个算法和目前最快的算法比起来不算突出,我用同样的机器,用另一种更快但也更复杂的算法计算查找999999999(9亿)内的//素数耗时是80.968000毫秒end = clock() - start;printf("%lld(%lld亿)内的素数个数为%lld,计算用时[%lf]毫秒\n",MaxInt,MaxInt/100000000,CntPrime,(double)end/1000);
}
//---------------------------------------------------------------------------------------
int main()
{ll  MaxInt,CntPrime;ll  PrimeListLen;int tmpval;CntPrime=0;//输入范围,即查找所有小于n的素数printf("\n请输入需计算素数的范围上限,输入0则结束运行:");cin>>MaxInt;if(MaxInt<1) return 0;PrimeListLen=MaxInt/2+1; //其实可以用Pi(x)计算更准确的个数,以节约运行所需内存,这里懒得写了//存放找到素数的动态数组ll *PrimeList =new ll[PrimeListLen];//调用getPrime函数搜索小于n的所有素数CalPrime(MaxInt,CntPrime,PrimeList);//打印输出找到的质数个数,提问是否保存到本地文件//999999999内的素数存到CSV文件,大小是478MBprintf("\n需把小于等于[%lld]的全部[%lld]个素数保存到CSV文件吗?(不保存请输入0)",MaxInt,CntPrime);char filename[128];cin>>tmpval;if(tmpval<1){delete PrimeList;return 0;}sprintf(filename,"./prime-in-%lld.csv",MaxInt);printf("\n下面开始把所有合计[%lld]个小于等于[%lld]的质数写入文件【%s】.....",CntPrime,MaxInt,filename);ofstream out(filename,ios::app);//app表示每次操作前均定位到文件末尾if(out.fail()){cout<<"error\n";}for(ll i=0;i<CntPrime;i++)out<<PrimeList[i]<<",";out.close();printf("\n小于【%lld】的[%lld]个质数已全部写入到文件[%s]\n",MaxInt,CntPrime,filename);delete PrimeList;   //删除保存素数的数组,回收内存return 0;
}
//---------------------------------------------------------------------------------------

下图是第一种算法运行的效果:

我尝试把10亿以内的所有5084千万多个素数写到CSV文件试了一下,文件的大小是478MB。

第二种算法的代码:

/*功能:查找所有小于等于指定整数的素数,上限是输出小于等于9223372036854775807的全部质数这是目前能找到的,最高效的查找素数算法*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <time.h>
#include <math.h>
#include <bits/stdc++.h>
#include <iostream>
#include <vector>
using namespace std;#define __int64 long long
__int64 *primarr, *v;
__int64 q = 1, p = 1;//π(n)
__int64 pi(__int64 n, __int64 primarr[], __int64 len)
{__int64 i = 0, mark = 0;for (i = len - 1; i > 0; i--) {if (primarr[i] < n) {mark = 1;break;}}if (mark)return i + 1;return 0;
}//Φ(x,a)
__int64 phi(__int64 x, __int64 a, __int64 m)
{if (a == m)return (x / q) * p + v[x % q];if (x < primarr[a - 1])return 1;return phi(x, a - 1, m) - phi(x / primarr[a - 1], a - 1, m);
}__int64 prime(__int64 n)
{char *mark;__int64 mark_len;__int64 count = 0;__int64 i, j, m = 7;__int64 sum = 0, s = 0;__int64 len, len2, len3;mark_len = (n < 10000) ? 10002 : ((__int64)exp(2.0 / 3 * log(n)) + 1);//筛选n^(2/3)或n内的素数mark = (char *)malloc(sizeof(char) * mark_len);memset(mark, 0, sizeof(char) * mark_len);for (i = 2; i < (__int64)sqrt(mark_len); i++) {if (mark[i])continue;for (j = i + i; j < mark_len; j += i)mark[j] = 1;}mark[0] = mark[1] = 1;//统计素数数目for (i = 0; i < mark_len; i++)if (!mark[i])count++;//保存素数primarr = (__int64 *)malloc(sizeof(__int64) * count);j = 0;for (i = 0; i < mark_len; i++)if (!mark[i])primarr[j++] = i;if (n < 10000)return pi(n, primarr, count);//n^(1/3)内的素数数目len = pi((__int64)exp(1.0 / 3 * log(n)), primarr, count);//n^(1/2)内的素数数目len2 = pi((__int64)sqrt(n), primarr, count);//n^(2/3)内的素数数目len3 = pi(mark_len - 1, primarr, count);//乘积个数j = mark_len - 2;for (i = (__int64)exp(1.0 / 3 * log(n)); i <= (__int64)sqrt(n); i++) {if (!mark[i]) {while (i * j > n) {if (!mark[j])s++;j--;}sum += s;}}free(mark);sum = (len2 - len) * len3 - sum;sum += (len * (len - 1) - len2 * (len2 - 1)) / 2;//欧拉函数if (m > len)m = len;for (i = 0; i < m; i++) {q *= primarr[i];p *= primarr[i] - 1;}v = (__int64 *)malloc(sizeof(__int64) * q);for (i = 0; i < q; i++)v[i] = i;for (i = 0; i < m; i++)for (j = q - 1; j >= 0; j--)v[j] -= v[j / primarr[i]];sum = phi(n, len, m) - sum + len - 1;free(primarr);free(v);return sum;
}
//---------------------------------------------------------------------
int main()
{__int64 n;__int64 count;int h;clock_t start, end;n=10000;while(n>1){printf("\n请输入需计算的整数上限,输入0则结束运行:");//输入范围,即查找所有小于n的素数cin>>n;if(n==0)  break;p=1;q=1;start = clock();count = prime(n);end = clock() - start;printf("%lld(%lld亿)内的素数个数为%lld\n",n,n/100000000,count);printf("用时%lf毫秒\n",(double)end/1000);}return 0;
}
//---------------------------------------------------------------------

下图是第二种算法计算10亿以内所有素数的输出截图:

计算万亿范围内的所有素数,耗时39秒。

(如果觉得有帮助,请点个赞鼓励下作者吧^_^)

快速查找计算9百万万亿整数内全部素数(质数)的C++代码相关推荐

  1. 用Java计算圆周率的十亿位_新世界纪录:谷歌将圆周率计算到 31 万亿位

    为了挑战更精确的圆周率,谷歌工程师 Emma Iwao 在25台谷歌云的虚拟机上,执行专为圆周率设计的算法,计算出31万亿数字的圆周率. 3.1415926,相信不少人都背诵过这串数字,并将它代入算式 ...

  2. 圆周率一千万亿位_圆周率计算已经达到数万亿位,为何还在继续计算?

    展开全部 计算圆周率e68a843231313335323631343130323136353331333433653962是数学家的兴趣,也能检验计算机的综合性能. 圆周率算法 圆周率是数学中最重要 ...

  3. 仅用 480 块 GPU 跑出万亿参数!全球首个“低碳版”巨模型 M6 来了

    继今年 3 月阿里达摩院发布国内首个千亿参数多模态大模型 M6(MultiModality-to-MultiModality MultitaskMega-transformer,以下简称 M6) 之后 ...

  4. 圆周率 π 小数点第 100 万亿数字是多少?Google 用 Debian 服务器给出了答案

    整理 | 苏宓 出品 | CSDN(ID:CSDNnews) π=3.1415926...... 想必学生时代,当提及背诵圆周率 π 小数点后面的个数时,很多人的胜负欲在悄然之间被激起,"只 ...

  5. 圆周率一千万亿位_圆周率已被算到60万亿位,继续算下去有何意义这里告诉你真正原因...

    圆周率或许是我们最熟悉的一个数学数值了,因为它有一个非常形象的代号"π",还有一个好记的数值"3.1415926",朗朗上口的数字让人对圆周率这个数学常数无法忘 ...

  6. 圆周率一千万亿位_“圆周率”已精确到60万亿位,算下去有何意义?专家告诉你真相!...

    "圆周率"已精确到60万亿位,继续算下去有何意义? 专家告诉你真相! 圆周率的有用性一直是一个争论的问题,尽管它受到许多数学爱好者的喜爱.圆周率的学名叫π,是数学中研究最多的数字, ...

  7. 字节跳动自研万亿级图数据库 图计算实践 【太高级了,不是圈里的人,有简明见解的吗?】

    1. 图状结构数据广泛存在 字节跳动的所有产品的大部分业务数据,几乎都可以归入到以下三种: 用户信息.用户和用户的关系(关注.好友等): 内容(视频.文章.广告等): 用户和内容的联系(点赞.评论.转 ...

  8. 字节跳动自研万亿级图数据库 图计算实践

    本文选自"字节跳动基础架构实践"系列文章. "字节跳动基础架构实践"系列文章是由字节跳动基础架构部门各技术团队及专家倾力打造的技术干货内容,和大家分享团队在基础 ...

  9. excel统计行数_百万到亿级数据,快速统计查询

    大家好,我是dk.这是Excel神器PowerQuery实战入门系列的第3篇.往后,我会更新更多关于PQ的相关内容,有兴趣的小伙伴可以关注下. 众所周知,Excel2003版最大行数是65536行,到 ...

最新文章

  1. 企业ERP制度的“执行力”
  2. 自学机器学习课程怕踩雷?有人帮你选出了top 5优质课
  3. 2010-07-18 项目重构计划
  4. 信息系统项目管理师-战略管理知识点
  5. windows 下的文件对比工具
  6. iOS下数据存储的方式
  7. qq撤回的消息会在服务器,如何查看qq撤回的消息_查看qq被撤回消息的方法
  8. python题目-判断素数
  9. jquery实现多选框
  10. GPT2.0语言模型 Language Models are Unsupervised Multitask Learners
  11. 查看源文件默认编辑器打开
  12. H5小游戏——看你有多色
  13. 【阿里云】短视频SDK产品
  14. FIL WORLD开启算力众筹新篇章,与世界一起助力FIL
  15. 尼康D500套机相机黑屏是怎么回事
  16. 设计分享 | 基于51单片机实现红外控制系统控制电机调速
  17. 技术2---swagger2
  18. 软盘是什么_什么是软盘?
  19. vue项目 el-input输入框字符限制,只显示英文及数字
  20. java集合听课笔记之hashMap的底层数据结构

热门文章

  1. 【OBS】OBS预览
  2. oracle存储过程批量导入数据,Oracle 存储过程之批量添加数据
  3. 自我高数学习笔记——知识点
  4. 蓝牙脂肪秤模块测量原理
  5. NYOJ-61 传纸条 双线动态
  6. 杨天宇20180912-3 词频统计
  7. R语言和医学统计学(6):重复测量方差分析
  8. OpenCV实战(7)——OpenCV色彩空间转换
  9. 歌曲:我愿爱(tvb台庆剧插曲)
  10. 光盘刻录播系统服务器,派美雅全自动光盘刻录审讯主机解决方案,行业应用 派美雅PRIMERA中国...