有一次面试给了我一台笔记本,要求现场求素数,虽然感觉有点突兀但是总比上次要求用笔在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 ",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 ", 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