找出21亿以内的所有素数需要多久?——使用free pascal

2 篇文章 0 订阅
1 篇文章 0 订阅

最近在学习free pascal,看到书上的筛选素数的算法,很简单,很粗暴,我很喜欢.但是死理性派的想法涌上心头在[2,MAXLONGINT]之间究竟有多少个素数呢?哦,忘了说MAXLONGINT=2147483647;没错就是21亿多.虽然不清楚有多少个素数,但有一点是可以肯定,找出这些素数一定是一个漫长的过程.之前做了一个小小的测试,在[2,MAXINT] (MAXINT=32767)之间一共有3512个素数,平均用时为0.24s左右.那么使用相同的代码找出21亿内的所有素数需要多久呢?显然,这不是一个按比例能够算出来的东西,一个是随着数字的增大需要进行的循环和计算量也在逐步上升,二来素数的分布并非是均匀的.so,我们需要实地的计算来告诉我们答案.当然,这只是一个很粗略的计算,只是用一个很不精致的算法,在一台很没有代表性的计算机上进行的一次测试,更何况,在进行测试的时候还没有严格的控制当时系统的软件环境,很可能笔者一边进行测试一边看着浏览器写博客.Anyway,我还是进行了测试,不为所谓”严谨”、所谓”科学”,只为满足自己小小的好奇心,仅此而已.


OK,进入正题.第一:什么叫素数?如果你还能找出小学课本的话,那这应该不算个问题.百科告诉我们:质数,又称素数,是一个大于1的自然数,除了1和它本身外,不能被其他自然数(质数)整除,换句话说就是该数除了1和它本身以外不再有其他的因数.定义很简单,但是关于素数的问题却引发了数学界许多著名的猜想和理论.如果说我们与古人相比有什么优越之处的话,那并不是我们有更为智慧的头脑,而是我们有更强大的工具.甚至于在智慧方面某种程度上我们的祖先要远远超过我们.第二个问题:如何找出这些素数呢?答案就在第一个问题,判断n是否为素数只要用n去除以2,3,4,…,sqrt(n),看能不能能找到第二个因数.具体来说,核心算法是这样的:

 for currentNum :=2 to MAXLONGINT do
 begin
  check := true;
  if (currentNum mod 2 =0) and (currentNum <> 2) then
     continue
   else
   begin
    for tmp :=2 to trunc(sqrt(currentNum)) do
    begin 
     if(currentNum mod tmp = 0) then
     begin
      check := false;
      break;//此处break会退出这个循环,跳到end;{mark1}处继续执行下去
     end;
    end;{mark1}
     if ((check) or (currentNum=2)) then
     begin
       total := total+1;
       if linecnt >= 10 then
       begin
        writeln;
        linecnt :=0;
       end;
       write(currentNum:11);
       linecnt := linecnt+1;
     end;
   end;
  end;
 //寻找结束

可能中间夹杂了一些控制输出的变量和语句,不太好了解,所以贴出所有代码:

{
  寻找素数
}
program findPrime;
var 
 currentNum,tmp,total:longint;
 linecnt:integer;
 check:boolean;//是否有其他因数
begin
 writeln('素数表');
 linecnt :=0;
 total :=0;

 for currentNum :=2 to MAXLONGINT do
 begin
  check := true;
  if (currentNum mod 2 =0) and (currentNum <> 2) then
     continue
   else
   begin
    for tmp :=2 to trunc(sqrt(currentNum)) do
    begin 
     if(currentNum mod tmp = 0) then
     begin
      check := false;
      break;//此处break会退出这个循环,跳到end;{mark1}处继续执行下去
     end;
    end;{mark1}
     if ((check) or (currentNum=2)) then
     begin
       total := total+1;
       if linecnt >= 10 then
       begin
        writeln;
        linecnt :=0;
       end;
       write(currentNum:11);
       linecnt := linecnt+1;
     end;
   end;
  end;
 //寻找结束
 writeln;
 writeln('共发现:',total,'个');
 writeln('-----end------');
end.

好了,编译、运行
fpc find_prime.pas
./find_prime
不过很快我就意识到我犯了一个错误!!!我应该要把结果重定向到一个文件里的,这样我就能把所有找到的素数保存下来了,但是……我并没有这样做.


程序运行一段时间了

大概一个小时后,大概计算到3亿6千万左右……
我的CPU正在燃烧

晚上7点左右,11亿了,风扇仍在狂转……
19:06:44

突然从梦中惊醒,总觉得还有什么没有做完的事,爬起来一看,果然,还在运行
04:31:55

终于结束了,漫长的旅程……此时是凌晨04:33:55
04:33:50

看看什么时候开始的吧
开始

我们从13:02:42开始,次日04:33:55结束,一共用了大约15h31min

我的机器和平台:
配置和平台


看到了吗?在[2,2147483647]之间有105097565个素数,而且有趣的是2和2147483647既然都在此列

我不知道我的运算准不准确,反正,就是这样了,我是不想再算一次了…..

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值