这篇文章同样是关于我读编程珠玑的一些体会与感想,这是关于计算素数算法优化的一些感想。
在学C语言的时候,用程序打印出某个范围内的所有素数的练习题大家都不陌生,我当时想到的算法类似下面这样的。
int prime(int n)
{
int i;
for(i=2;i<n;i++)
if(n%i==0)
return 0;
return 1;
}
main()
{
int i;
int n=10000;
for(i=2;i<=n;i++)
if(prime(i))
printf("%d\n", i);
}
for(i=2;i<=sqrt(n);i++)
但是作者用性能监视工具发现第二种算法并没有比第一种算法快,反而慢了许多,原因是sqrt会占用很多的CPU时间,而for循环每次都要执行一次sqrt,这才导致了算法二变慢,所以把sqrt放到for()循环外面。
int m=sqrt(n);
for(i=2;i<=m;i++)
{····}
但是作者还是觉得循环是累赘,有提供了下面的算法,思想大概是这样,对能被2、3、5整除的数进行检验,然后在将奇数作为可能因子(我怎么想不到大于2的偶数都不可能作为因子呢,笨···)。
int prime(int n)
{
int i,m;
if(n%2==0)
return (n==2);
if(n%3==0)
return (n==3);
if(n%5==0)
return (n==5);
m=sqrt(n);
for(i=7;i<=m;i=i+2)
if(n%i==0)
return 0;
return 1;
}
后来作者考虑到sqrt比较费时,所以对循环做了如下修改(不得不佩服啊~)。
for(i=7;i*i<=n;i=i+2)
看完之后想了想,如果在数据量相当大的情况下,用算法一不知道要花多少时间啊,根据作者的监测,当n=100000时,算法一由于时间太长没法给出具体数字,算法二用了近3000秒,而最后一种把开方换成乘法用了一分钟左右,当然这些时间数据是在作者机器上的运行时间。此时深刻体会到良好的算法设计可以大大提高程序的效率。