题目:
请实现一个函数,对于给定的整型参数N,依次打印出小于N的素数。
解法一:试除法
由素数的定义我们很自然的会想到如下代码:
#include <stdio.h> void print_prime(int n) { int i=0; for(i=2;i<=n;i++) { int j=0; for(j=2;j<i;j++) { if(0==i%j) break; } if(j==i) printf("%d\t",i); } } int main() { int num=0; scanf("%d",&num); print_prime(num); return 0; }
在上面的代码中,我们看到在判断素数时一直从2试除到n-1。这里从n/2之后的数到n-1的试除显然是多余的,比如某个数不能被3整除,必然不能被6整除。
优化1:
试除的范围优化到[2,n/2],这样一下子就将工作量减少了一半,代码如下:
void print_prime(int n) { int i=0; for(i=2;i<=n;i++) { int j=0; for(j=2;j<=i/2;j++) //修改部分 { if(0==i%j) break; } if(j==(i/2+1)) //修改部分 printf("%d\t",i); } }
既然能将试除范围优化到[2,n/2],那么这个范围是不是还能优化呢?答案是可以的,在[2,n/2]这个范围里(√n,n/2]的试除也是多余的。因为因数是成对出现的,比如16可分解为:1和16 、2和8、4和4、8和2、16和1。这些因数里必然有一个小于等于4。所以只需试除小于等于√n的数就可以了。
优化2:
试除范围优化为[2,√n],代码如下:
#include <stdio.h> #include <math.h> void print_prime(int n) { int i = 0; for (i = 2; i <= n; i++) { int j = 0; for (j = 2; j <= sqrt(i); j++) //修改部分 { if (0 == i%j) break; } if (j >sqrt(i)) //修改部分 printf("%d\t", i); } } int main() { int num = 0; scanf("%d", &num); print_prime(num); return 0; }
上面所有的代码在找素数的时候是从2到n,在这个范围内除了2之外的偶数都不是素数,所以我们可以跳过这些偶数。
优化3
寻找素数时跳过偶数,这样工作量就少了一半。代码如下:
void print_prime(int n) { int i = 0; if (n >= 2) printf("%d\t", 2); for (i = 3; i <= n; i+=2) { int j = 0; for (j = 2; j <= sqrt(i); j++) { if (0 == i%j) break; } if (j >sqrt(i)) printf("%d\t", i); } }
时间: 2024-09-29 02:23:08