有一次面试给了我一台笔记本,要求现场求素数,虽然感觉有点突兀但是总比上次要求用笔在A4纸张上实现开平方根函数要像样的多。
我没有立马开始写,而是在那里发呆,我在想他想从我这里了解到什么?
至少这个程序需要考虑到以下几个问题:
1、程序原理上的正确性,至少结果必须是100%正确的。
2、程序的性能,求素数是一个很考验算法的简单问题,算法不好给一个大点的数半天都算不完,所以这就考虑到简单的算法设计,毕竟是现场写不能想太久太复杂的算法。
3、编程风格。
搞清楚了“需求”,接下来就是实现。
素数的定义如下
质数(prime number)又称素数,有无限个。
质数定义为在大于1的自然数中,除了1和它本身以外不再有其他因数。
如果按照素数的定义去写,原理上当然正确,但是效率太低。
先从数学原理上分析素数,
1、偶数肯定不是素数(2这个特例先踢出去),所以第一步先把能被二整除(0 == (n % 2))的偶数剔除,这就降低了一半的计算量。
2、如果不是素数,至少还有其他两个因素,那么其中一个因素至少小于等于他的平方根。
于是代码就可以如下设计
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<math.h>
#define MAX (100000)
#define MIN 2
int main()
{
int i = 0, j = 0;
for(i = 2; i <= MAX; ++i)
{
if(MIN == i)
{
printf("prime:%d\n",i);
continue;
}
else if(0 == (i % 2))
continue;
for(j = 3; j < (sqrt(i) + 1); j += 2)
{
if( 0 == i % j)
break;
}
if( j >= sqrt(i) + 1)
printf("prime:%d\n", i);
}
return 0;
}
内层循环只拿奇数整除,因为偶数在第一轮排除掉了。
这个算法不是最优,但是也不是最笨的,性能上还是过得去的。
实测计算10万以内耗时0.172s
real 0m0.172s
user 0m0.024s
sys 0m0.076s
计算100万以内耗时10.1s
real 0m10.109s
user 0m0.952s
sys 0m0.576s
计算1000万以内耗时1分39.2s
real 1m39.208s
user 0m25.358s
sys 0m4.860s