求质数1 C实现

来源:互联网 发布:mac pro测评 编辑:程序博客网 时间:2024/05/16 01:51

该问题出自《C语言名题精选百则技巧篇》

试编写一个程序,找出前N(如200)个质数。

    最初想到的办法就是让某个变量i从2到N,然后检查它是不是质数,如果是的话就显示出来,如果不是就检查下一个,这样会让程序变的很慢,每一个要检查的数i,都要被2~i-1,除,如果余数为0则不是质数,如果全部余数都不为0,则该数是质数。我们现在想办法来缩小范围。包括待检测的变量的范围和检测变量需要的被除数2~i-1

(1)缩小待检测的变量的范围

    我们可以考虑到,2是质数,但是所有2的倍数都不是质数,如果让i从2变到N,就会很冤枉的测试了4,6,8,10,....这些2的倍数,因此在待测试的变量里将除去2以外的偶数都去掉,只测试2和奇数;

     另外,3是质数,所有3的倍数都不是质数,因此也可以将3的倍数去掉不测试;

     现在能将所有2和3的倍数都去掉,将6的倍数去掉,任意连续的6个数,6n,6n+1,6n+2,6n+3,6n+4,6n+5,这六个数里,6n是6的倍数,6n+2是2的倍数,6n+3是3的倍数,6n+4是4的倍数,在这连续的6个数里,至少包含两个2的倍数和1个3的倍数,在这6个数里,需要检测的变量只有6n+1和6n+5,因此现在工作量变成了原来的2/6=1/3.

    并且我们可以计算要考虑的这些之间的规律,6n,6n+1,6n+2,6n+3,6n+4,6n+5,当n=i-1时要测试的最后一个值与n=i时要测量的第一个值的距离是2,本组第一个要测试的值和第二个要测试的值之间的距离是4,因此,距离是2,4,2,4...可以让待测试的值从5开始,即i=0时的最后一个值开始,初始gap=2,下一个值就是6-gap(4),下一次是6-gap(2)。

(2)缩小被除数的范围

    我们之前考虑被除数是2~i,按照质数的定义,若i只能被1和i本身整除,那么i是质数,否则i不是质数。所以我们需要用2,3,4,5,6,...,i-1去除i,如果都除不尽,则i是质数。

     但是我们可以想一想,当i>2时,有没有一个整数可以被i-1整除的,没有,因为如果i不是质数,那么i=a*b,a和b既不是1也不是i,因此,a和b的最小值为2,假设a<b,则a>=2,b<=i/2,如果i能被a整除,就一定能被b整除,因此,去除i的数用不着是2~i-1,只要是a和b里面最小的那个值a的范围就可以了,因此可以将范围缩小到2~i/2。

     那么2~i/2是否还可以缩小范围呢,i=a*b,a和b不同同时大于根号i,因为如果a和b都比根号i大,则a*b>i,因此,a不能大于根号i,a和b里面的小的那个数a的范围又缩小了,2~根号i,现在去除i的数缩小范围到2~根号i。

      现在我们还想继续缩小范围,和缩小待检测数的范围相同,如果2除i除不尽,那么2的倍数去除i也除不尽;同理3除不尽,3的倍数也除不尽,5除不尽,5的倍数也除不尽,最理想的方法就是用质数去除i,因此范围缩小到用小于根号i的质数去除i即可。因为和根号i比较可能并不精确,因此可以使prime[i]*prime[i]和i相比。prime[i]为最新检测出的质数。

程序如下:

#include <stdio.h>#define MAXSIZE  100#define YES      1#define NO       0int main(int argc,char *argv[]){int prime[MAXSIZE];int gap =2;int count =3;int may_be_prime = 5;int i,is_prime;prime[0] = 2;prime[1] = 3;prime[2] = 5;while(count <MAXSIZE){    may_be_prime += gap;    gap = 6-gap;    is_prime = YES;    for(i=2;prime[i]*prime[i]<=may_be_prime&&is_prime;i++)    if(may_be_prime%prime[i] == 0)        is_prime = NO;    if(is_prime)        prime[count++] = may_be_prime;            }printf("\nPrime Number Generation Program");printf("n================================\n");printf("\nFirst %d Prime Numbers are:\n",count);for(i=0;i<count;i++){    if(i%10 ==0)     printf("\n");    printf("%5d ",prime[i]);}getchar();return 0;}
运算结果



0 0
原创粉丝点击