求质数实现算法

求i到j之间的所有质数
第一种方法:效率最差,是把i到j之间的每一个数n,都拿出来,挨个循环用n除以从2到n-1的所有整数,如果期间有一个能整除,那么n是合数,继续下一个。


第二种方法:,效率稍好,比第一种方法效率提高一倍,是把i到j之间的每一个数n,都拿出来,挨个循环用n除以从2到n/2的所有整数,如果期间有一个能整除,那么n是合数,继续下一个。

第三种方法:算法效率就高了很多,利用合数定理——如果一个数是合数,那么它的最小质因数肯定小于等于他的平方根。如50的最小质因数是2,它的平方根是7.07,2<=7.07。也可以用反证法证明。

(设a = bq,因为a是合数,则b和q都是大于1的整数.又设q是a的最小质因数,即b>=q.如果q<=根号a不成立,则必有 q>根号a,此时更有b > 根号a,于是a = bq > 根号a*根号a =  a  出现矛盾,故q <=根号a证毕.  )

利用这个原理,只需将i和j之间得某个数n取出,并用循环将n除以从2到根号n之间的所有整数如果期间存在一个数可以整除,那n为合数,否则为质数。

View Code
 1 class Program
 2     {
 3         static bool isprimenum(int a)
 4         {
 5             int i = 2;
 6             while (i <= Math.Sqrt(a))
 7             {
 8                 if (a % i == 0)
 9                 {
10                     Console.WriteLine("您输入的不是素数");
11                     return false;
12                 }
13                 i++;
14 
15             }
16             Console.WriteLine("您输入的是素数");
17             return true;
18         }
19         static void Main(string[] args)
20         {
21             Console.Write("请输入:");
22             int num = Console.Read();
23             isprimenum(num);
24         }
25 
26     }

 第四种方法:是效率最高的一种方法。首先建立一个布尔型1维数组a,长度为j-i,初始值为true。首先用第三种方法求得i、j之间的第一个质数m。求得m 以后,将所有小于i的m的倍数所在的数组(即a[m的倍数-i])位置全部设为false。然后进行下一步,从n=m++开始,如果a[n-i]已经被设 置为false,则n++,直到出现首个为true的位置p,再将所有小于i的p的倍数所在的数组位置置为false。继续下一步,直到n>根号j 为止,这样所有为true的数组id(如果i=1则0除外,id从1开始)+i 即为质数。

举个例子。例如要查找 2-100之间的质数,首先2是质数,把2的倍数去掉(比如4,6,8,...,100,对应的数组位置是a[m-2]即 a[2],a[4],a[6],...,a[98],将这些位置设为false);进行下一步,此时3没有被去掉(a[2]=true),可认为是质数, 所以把3的倍数去掉(a[5]a[8]a[11],...,a[98]=false);再到5,再到7,7之后呢,因为8,9,10刚才都被去掉了,而 100以内的任意合数的最小质数因子肯定小于等于10(100的开方),所以,去掉,2,3,5,7的倍数后剩下的都是质数了。最后只要将a[id]中所 有等于true的id值加上i输出即可。按照这个例子是id+2,比如0+2,1+2,3+2,...
相对来说这种算法求1到n之间的质数实现起来比较简单,如果是求任意两个数之间的质数,逻辑上会比较复杂。但是,效率的确提高了很多很多。

第四种方法的C#实现代码如下:

View Code
 1 class Program
 2      {
 3           static public int ffirst(int n)//找到范围要求内的最小质数,这里为2
 4          {
 5               int a=2;
 6               while (a < n)
 7               {
 8                   int i = 2;
 9                   while (i <= Math.Sqrt(a))
10                   {
11                       if (a % i == 0)
12                       {
13                           a++;
14                           i = 0;//把I置为0,代表已经测得当前这个数不是质数然后跳出循环
15                           break;
16                       }
17                       i++;
18                   }
19                   if (i != 0)
20                   {
21                       return a;
22                   }           
23                   
24               }
25               return -1;
26              //Console.WriteLine("您输入的是素数");
27              
28          }
29          static void Main(string[] args)
30         {
31              const int N=100;//求1--100之间的质数
32              int Num=ffirst(N);
33              bool[] array=new bool[N];//定义bool类型数组,true代表是质数
34              for (int i = 0; i < array.Length; i++)//赋初值
35             {
36                  array[i] = true;
37              }
38              while (Num <= Math.Sqrt(N))//100以内的任意合数的最小质数因子肯定小于等于10(100的开方)
39              {
40                  int k = Num;//k存储的是程序执行过程中当前的最小质数,因为 while(!array[Num++]);已经跳过了置为false的数值
41                  while (k < N)
42                  {
43                      if ((k+1) % Num == 0)
44                      {
45                          array[k] = false;
46                      }
47                      k++;
48                  }    
49                  //Num++; 
50                 while(!array[Num++]);//哈哈,终于搞定了!开始怎么都实现不了避开前面已经置为false的数值,就采用了遍历2到N的方法
51                  //最后一句代码就搞定了,嘻嘻
52             }
53              
54              for (int x = 1; x < N; x++)
55              {
56                  if (array[x])
57                  {
58                     Console.Write((x+1)+" ");
59                  }
60              }
61          }
62      }
63 }

转载于:https://www.cnblogs.com/fighting-mochou/archive/2012/11/06/mochou.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值