最近在学习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千万左右……
晚上7点左右,11亿了,风扇仍在狂转……
突然从梦中惊醒,总觉得还有什么没有做完的事,爬起来一看,果然,还在运行
终于结束了,漫长的旅程……此时是凌晨04:33:55
看看什么时候开始的吧
我们从13:02:42开始,次日04:33:55结束,一共用了大约15h31min
我的机器和平台:
看到了吗?在[2,2147483647]之间有105097565个素数,而且有趣的是2和2147483647既然都在此列
我不知道我的运算准不准确,反正,就是这样了,我是不想再算一次了…..