一个快速判断素数的方法

    平常我们用暴力破解来判断n是否是素数时,都是用n试除2到√‾n判断的。但其实这中间就多了很多冗余的判断了,例如:一个数不能被2整除,那就证明了它不能被4、6、8这样的能被2整除的数整除。我们将这些冗余的数去除掉之后就能加快判断的速度。

    那么,将这样的冗余的数去除之后的数会出现什么样的规律呢?我们先拿2和3来测试一下,计算一个数和前一个数的差并全部输出:

 1 #include <stdio.h>
 2 #include <stdlib.h>
 3 
 4 int main(int argc, char *argv[]) 
 5 {
 6     long i, last = 7;
 7     for (i = 8; i < 1000; i++)
 8     {
 9         if (i % 2 != 0 && i % 3 != 0)
10         {
11             printf("%d ", i - last);
12             last = i;
13         }
14         if ((i - 7) % 6 == 0)
15             printf("\n");
16     }
17     return 0;
18 }

    这个程序的运行结果为:

4 2
4 2
4 2
4 2
4 2
4 2
4 2
4 2

......

    加上5之后的结果是:

4 2 4 2 4 6 2 6
4 2 4 2 4 6 2 6
4 2 4 2 4 6 2 6
4 2 4 2 4 6 2 6
4 2 4 2 4 6 2 6

......

    加上7之后的记过是:

4 2 4 2 4 6 2 6 4 2 4 6 6 2 6 4 2 6 4 6 8 4 2 4 2 4 8 6 4 6 2 4 6 2 6 6 4 2 4 6 2 6 4 2 4 2 10 2 10 2

4 2 4 2 4 6 2 6 4 2 4 6 6 2 6 4 2 6 4 6 8 4 2 4 2 4 8 6 4 6 2 4 6 2 6 6 4 2 4 6 2 6 4 2 4 2 10 2 10 2

4 2 4 2 4 6 2 6 4 2 4 6 6 2 6 4 2 6 4 6 8 4 2 4 2 4 8 6 4 6 2 4 6 2 6 6 4 2 4 6 2 6 4 2 4 2 10 2 10 2

4 2 4 2 4 6 2 6 4 2 4 6 6 2 6 4 2 6 4 6 8 4 2 4 2 4 8 6 4 6 2 4 6 2 6 6 4 2 4 6 2 6 4 2 4 2 10 2 10 2

......

    这些数在一个周期内保持一定规律,而周期则是被除数的最小公倍数。显然当使用7时,在周期内的数的规律太长了,使用5则恰到好处。

    至此,我们差不多可以用代码实现了。我们知道10以内的素数是2、3、5、7,那么可以先将这些数剔除了,从大于7的数开始。先判断需计算的数能不能被2、3、5整除,然后再使用上面第二个规律,使用周期30来试除。代码实现如下:

 1 #include <stdio.h>
 2 #include <stdlib.h>
 3 
 4 int prime(long n)
 5 {
 6     if (n <= 5)
 7     {
 8         if (n == 2 || n == 3 || n == 5 || n == 7)
 9             return 1;
10         return 0;
11     }
12     else
13     {
14         long s = sqrt(n), step = 7;
15         if (n % 2 == 0 || n % 3 == 0 || n % 5 == 0)
16             return 0;
17         while (step <= s)
18         {
19             if (n % step == 0)
20                 return 0;
21             step += 4;
22             if (n % step == 0)
23                 return 0;
24             step += 2;
25             if (n % step == 0)
26                 return 0;
27             step += 4;
28             if (n % step == 0)
29                 return 0;
30             step += 2;
31             if (n % step == 0)
32                 return 0;
33             step += 4;
34             if (n % step == 0)
35                 return 0;
36             step += 6;
37             if (n % step == 0)
38                 return 0;
39             step += 2;
40             if (n % step == 0)
41                 return 0;
42             step += 6;
43         }
44     }
45     return 1;
46 }

    使用这个方法,程序的时间复杂度相当于暴力破解的8/30,即8*O(n)/30。

 

 

posted @ 2013-11-23 12:54  joyingx  阅读(3040)  评论(0)    收藏  举报