标签:素数求解 试除法 筛法
题目:
请实现一个函数,对于给定的整型参数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);
}
}本文出自 “牛丽” 博客,请务必保留此出处http://15129279495.blog.51cto.com/10845420/1739802
标签:素数求解 试除法 筛法
原文地址:http://15129279495.blog.51cto.com/10845420/1739802