求素数列表和判断素数的算法
求素数的算法

求素数的算法
1. 定义
素数又称质数,是指只能被1和它本身整除的自然数,如2、3、5、7、11等,而4、6、8、9等都不是素数。
2. 筛法
筛法是一种较为简单的求素数的算法,主要原理是先假设所有数都是素数,然后从小
到大开始筛选,将所有能够整除当前数字的数标记为合数,剩余的就是素数。
具体步骤如下:
(1)初始化数组:将从2到n的所有整数存入数组中,初始时都标记为素数。
(2)循环遍历数组:从2开始循环遍历数组,将当前数字标记为素数,然后将所有能够整除当前数字的数标记为合数。
(实际上只需要循环到sqrt(n)即可)
(3)输出素数:遍历数组,输出所有标记为素数的数。
3. 质数判定法
如果只需要判断某一个给定的数是否是素数,那么可以采用质数判定法。
常见的质数
判定法有以下几种:
(1)试除法:从2开始到sqrt(n)依次尝试除n,如果能够整除则不是素数,否则是
素数。
这种方法速度较慢,但实现简单。
(2)根号判定法:如果一个数n不是素数,那么n可以表示为两个整数的乘积,即n = x * y。
这两个整数必然有至少一个小于等于sqrt(n)。
因此,只需要判断是否存在小于等于sqrt(n)的因数即可。
(3)费马小定理:如果n是素数,那么对于任意整数a,a^(n-1) mod n = 1。
根据这个定理,我们可以随机选取一些a进行计算,如果a^(n-1) mod n 不等于 1,则n一定不是素数,否则n可能是素数。
(4)米勒-拉宾素性判定法:该方法是一种基于费马小定理的扩展算法。
具体实现过
程较为复杂,但速度较快,能够判断很大的素数。
求素数列表和判断素数的算法

求素数列表和判断素数的算法有兴趣阅读本文的读者,应该对素数概念是十分熟悉的了。
用计算机程序实现素数计算,集中在2个主要问题上:∙判断一个正整数是否是素数-(算法A)∙求一定范围内的素数列表- (算法B)关于素数的算法,根据素数的数学性质,大家都会想到如下几个方面:∙用遍历求模的方式判断素数∙素数都是奇数,可以在奇数数列中寻找素数∙利用开方来缩小搜索的范围然后,求素数的计算是复杂的,如果算法写得不好,则耗时较高。
在百度百科“素数”条目中的算法程序,是值得商榷的。
很多方法是O(N2)的算法。
为此,在本文中探讨了求素数列表和判断素数这两个算法,力图使算法可以达到O(N Log(N))优化级别。
在本文中,算法语言选用C#。
1,判断素数的简单实现(算法A-1)///<summary>///算法A-1,判断素数///</summary>///<param name="number">待测正整数</param>///<returns>是否为素数(为了简化,1以下的整数皆为素数)</returns>public static bool IsPrime(int number){// 为了简化,1以下的整数皆为素数if(number <= 2){return true;}// 奇偶性if (number % 2 == 0){return false;}// 利用开方缩小范围,优化效果十分明显int range = (int)Math.Sqrt(number) + 1;// 从3开始的奇数列for (int current = 3; current <= range; current += 2){// 判断是否为素数if (number % current == 0){// 合数return false;}}return true;}A-1算法中,首先判断奇偶性,再判断从3开始判断待查数(number)是否是合数,若到Math.Sqrt(number)还没有查到是合数,即为素数。
素数常见的算法

求素数的三种方法
素数的定义:
素数也叫质数。
一个大于1的自然数,除了1和它本身之外,不能被其它自然数整除的数叫做素数;能被其它自然数整除的数叫做合数。
规定,1既不是质数也不是合数。
法一:试除法(判断素数)
让N被2如果N能被其中任何一个整数整除,则提前结束循环,N不是素数;如果N不能被其中任何一个整数整除,则N是素数。
代码实现:
法二:埃氏筛法(求一个范围中所有素数)
试除法可以用来判断一个数是否为素数,如果用来求某一范围内所有素数的话,效率就比较低。
埃氏筛法是用来解决这类问题的古老而简单高效的方法,可以快速找到[2,]n中的所有素数。
具体操作是这样的:从2开始寻找素数,每次找到一个素数后就将它的倍数全部筛掉,并将该素数存储到另一个数组中,不断循环,直到原数组为空。
法三:欧拉筛法(埃氏筛法的优化版)
埃氏筛法中,由于一个数可以既是一个素数的倍数,又是另一个素数的倍数,可以发现这会出现重复标记的情况,即同一个数被筛掉了不止一次,浪费操作了。
欧拉筛法就是在埃氏筛法的基础上多了判断的步骤,从而消失了这种重复标记的情况,核心思想是用合数中的一个因数筛掉这个合数。
具体操作为:利用已经求得的素数,第一重循环将区间内的数从小到大遍历,第二重循环将以求得的素数从小到大遍历,将这个数和素数的乘积标记为合数。
如果一个数能被素数整除,跳出循环。
素数的算法[精华]
![素数的算法[精华]](https://img.taocdn.com/s3/m/50a8484676232f60ddccda38376baf1ffc4fe388.png)
题目1:判断M是否为素数算法:让M被2到√M(M的开方)除,如果M能被2--√M之中任何一个整数整除,则提前结束循环,此时i必然小于或等于K(即√M);如果M不能被2--K(即√M)之间任何一整数整除,则在完成最后一次循环后,i还要加1,因此i=K+4,然后才终止循环.在循环之后判别i的值是否大于或等于K+1,若是,则表明未曾被2-K之间任一整数整除过,因此输出是"是素数".#include <iostream>#include <math.h>using namespace std;void main(){int i,k,m;cout<<"Please input the number:";while(cin>>m){k=sqrt(m);for(i=2;i<=k;i++)if(m%i==0) break;if(i>k)cout<<m<<" 是素数!"<<endl;elsecout<<m<<" 不是素数!"<<endl;}}//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////题目2:求2--100之间的素数.在题目1的基础上再加一个外层循环就可满足要求.#include <iostream>#include <math.h>using namespace std;void main(){int m,k,i,n=0;for(m=2;m<=100;m++){k=sqrt(m);for(i=2;i<=k;i++)if(m%i==0)break;if(i>=k+1){cout<<m<<" ";n=n+1;}if(n%10==0)cout<<endl;}cout<<endl;}/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////题3:求2--100的质数(效率越高越好)算法:先定义一个长100的数组,代表100以内的数,数组内所有数全部置1,并假定1表示是素数,0则不是素数。
有关素数判断的一些算法(总结对比)

有关素数判断的⼀些算法(总结对⽐)素性测试是数论题中⽐较常⽤的⼀个技巧。
它可以很基础,也可以很⾼级(哲学)。
这次主要要介绍⼀下有关素数判断的奇技淫巧素数的判断主要分为两种:范围筛选型&&单个判断型我们先从范围筛选型这种常⽤的开始讲起,这⾥采⽤模板题来进⾏测试1.埃⽒筛这是最常⽤的筛法了,思路也很简单:任何⼀个素数的倍数都是合数然后我们O(n)扫⼀遍,同时筛去素数的倍数但是有⼀些数如6,会被2和3都筛去⼀次,就造成了效率上的浪费,所以复杂度经证明为**O(n log log n)CODE#include<cstdio>using namespace std;const int N=10000005;bool vis[N];int n,m,x;inline char tc(void){static char fl[100000],*A=fl,*B=fl;return A==B&&(B=(A=fl)+fread(fl,1,100000,stdin),A==B)?EOF:*A++;}inline void read(int &x){x=0; char ch=tc();while (ch<'0'||ch>'9') ch=tc();while (ch>='0'&&ch<='9') x=x*10+ch-'0',ch=tc();}inline void get_prime(int m){register int i,j;for (vis[1]=1,i=2;i<=m;++i)if (!vis[i]) for (j=i<<1;j<=m;j+=i) vis[j]=1;}int main(){//freopen("CODE.in","r",stdin); freopen("CODE.out","w",stdout);read(n); read(m); get_prime(n);while (m--){read(x);puts(vis[x]?"No":"Yes");}return 0;}2.线性筛(欧拉筛)这其实是对上者的优化,我们意识到⼀个数应该只有它的最⼩质因数删去,所以我们可以⼀边筛数的同时⼀边记录素数,这就是真正的O(n)复杂度CODE#include<cstdio>using namespace std;const int N=10000005;int prime[N],n,m,x,cnt;bool vis[N];inline char tc(void){static char fl[100000],*A=fl,*B=fl;return A==B&&(B=(A=fl)+fread(fl,1,100000,stdin),A==B)?EOF:*A++;}inline void read(int &x){x=0; char ch=tc();while (ch<'0'||ch>'9') ch=tc();while (ch>='0'&&ch<='9') x=x*10+ch-'0',ch=tc();}inline void Euler(int n){register int i,j;for (vis[1]=1,i=2;i<=n;++i){if (!vis[i]) prime[++cnt]=i;for (j=1;j<=cnt&&i*prime[j]<=n;++j){vis[i*prime[j]]=1;if (!(i%prime[j])) break;}}int main(){//freopen("CODE.in","r",stdin); freopen("CODE.out","w",stdout);read(n); read(m);Euler(n);while (m--){read(x);puts(vis[x]?"No":"Yes");}return 0;}注意上⾯的那句话:if (!(i%prime[j])) break;这保证了线性筛的效率,不会产⽣重复,因为当i%prime[j]==0时这个数就是让后⾯的数删去。
素数的算法原理和应用

素数的算法原理和应用概述素数是指只能被1和自身整除的正整数。
素数在密码学、计算机科学和数学研究等领域具有重要的应用。
本文将介绍素数的算法原理以及在实际应用中的一些常见场景。
素数的判断算法判断一个数是否为素数是素数算法的基础。
常用的素数判定算法有两种:试除法和素数筛法。
试除法试除法是最简单直观的素数判定方法。
对于一个待判断的正整数n,只需从2开始遍历到sqrt(n)(即n的平方根)的整数m,检查是否有任何m能整除n。
若能找到能整除n的m,则n不是素数;否则,n是素数。
试除法的时间复杂度为O(sqrt(n)),适用于判断大部分整数是否是素数。
然而,对于非常大的数,这种方法的效率较低。
素数筛法素数筛法通过筛选法来判断素数。
其中最常用的是埃拉托斯特尼筛法。
首先,生成一个长度为n+1的布尔类型数组,将其初始值都设为true。
然后从2开始遍历到sqrt(n)的整数m,在数组中将2的倍数、3的倍数、4的倍数…全部标记为false。
最后,数组中值为true的索引对应的数就是素数。
素数筛法的时间复杂度为O(nloglogn),虽然比试除法高效,但由于需要生成一个长度为n+1的数组,对于非常庞大的数,也存在一定的限制。
素数的应用素数在密码学、计算机科学和数学研究等领域有广泛的应用。
以下是一些常见的素数应用场景。
密码学中的应用素数在密码学中起到至关重要的作用,特别是在公钥密码学中。
其中一个常见的应用是RSA加密算法。
在RSA算法中,首先需要生成两个大素数p和q,然后计算它们的乘积n=p*q。
n被用作加密和解密过程中的模数,而p和q用于生成公钥和私钥。
素数的随机性应用素数的随机分布属性使其成为生成随机数的重要组成部分。
例如,质数的随机分布性质被广泛应用在随机数生成算法中,确保生成的随机数能够满足安全性和随机性的要求。
整数因子分解素数在整数因子分解中也有重要应用。
由于素数只能被1和自身整除,因此在将一个大数分解成其因子时,可以使用素数的概念来加快计算过程。
求100以内的素数(质数)算法梳理

求100以内的素数(质数)算法梳理质数定理:1、从2开始到⾃⾝的-1的数中找到⼀个能整除的(从2开始到⾃⾝开平⽅的数中找到⼀个能整除的)。
2、⼀个合数⼀定可以分解成⼏个质数的乘积,也就是说,⼀个数如果能被⼀个质数整除就是合数。
(使⽤列表保存质数)使⽤定理1的基本写法:(1)n = 100for i in range(2, n):for j in range(2, i):if i % j == 0:breakelse:print(i, end='')这种基本写法效率不⾼,有2点可以改进的地⽅:1、第⼀层循环的i取值时,因为偶数确定不是质数,所以排除偶数,使⽤range()函数排除偶数,range(3, n, 2)这样就减少了⼀半的数。
2、第⼆层循环j取值时,考虑从2开始到i开平⽅取值,同时也把偶数排除range(3, int(i**0.5)+1, 2)这样也可减少⼀半的数。
2就是质数,单独打印。
(2)改进(1)n = 100print(2)for i in range(3, n, 2):for j in range(3, int(i**0.5)+1, 2):if i % j == 0:breakelse:print(i, end='')(3)再(2)的基础上还有优化的点,发现第⼀层循环i取值时,当i>10时,5的倍数也可排除n = 100print(2)for i in range(3, n, 2):if i > 10 and i % 5 == 0:continuefor j in range(3, int(i**0.5)+1, 2):if i % j == 0:breakelse:print(i, end='')(4)利⽤定理2,⽤列表保存上⼀次的运算结果n = 100L = [2]for i in range(3, n, 2):for j in L:if i % j == 0:breakelse:L.append(i)print(L)此种写法的效率不⾼,第⼀层循环的i没必要与列表中的每⼀个元素取余,与从2开始到i的开平⽅处之间的数取余即可。
素数判断问题

素数判断问题素数是指只能被1和本身整除的自然数。
对于给定的一个数,判断它是否为素数是一个常见且有趣的数学问题。
在本文中,我们将介绍几种素数判断的方法,并通过代码示例来实现。
一、暴力法暴力法是最直接的素数判断方法,即对于给定的数n,遍历从2到n-1的数进行整除运算,如果存在能整除n的数,则n不是素数;否则,n为素数。
代码实现如下:```pythondef is_prime(n):if n <= 1:return Falsefor i in range(2, n):if n % i == 0:return Falsereturn True```以上代码中,我们首先判断n是否小于等于1,因为1不是素数。
然后从2开始遍历到n-1,如果n能被任意一个数整除,则返回False,否则返回True。
这种方法简单易懂,但效率较低。
当n较大时,会进行大量的除法运算,耗费较长的时间。
二、优化方法在暴力法的基础上,我们可以进行一些优化,使判断素数的效率提高。
1. 去除偶数判断:除了2之外,所有的偶数都不可能是素数。
我们可以对代码进行优化,使其在判断n为偶数时直接返回False,减少不必要的运算。
代码实现如下:```pythondef is_prime(n):if n <= 1:return Falseif n == 2:return Trueif n % 2 == 0:return Falsefor i in range(3, int(n ** 0.5) + 1, 2):if n % i == 0:return Falsereturn True```2. 优化循环范围:对于一个数n,如果不存在小于等于n的因子,那么大于n的数也不可能是其因子。
我们只需要判断从2到√n的范围即可。
代码实现如下:```pythondef is_prime(n):if n <= 1:return Falseif n == 2:return Trueif n % 2 == 0:return Falsefor i in range(3, int(n ** 0.5) + 1, 2):if n % i == 0:return Falsereturn True```以上代码中,我们利用`int(n ** 0.5)`可以获取n的平方根,并将循环范围缩小到2到√n。
素数判定的递归算法

素数判定的递归算法素数判定是一个经典的数学问题,在计算机科学中也有着广泛的应用。
在解决这个问题时,可以使用递归算法来判断一个数是否为素数。
下面是一个使用递归算法进行素数判定的详细解释。
首先,什么是素数?素数又被称为质数,是指除了1和它本身外,无法被其他自然数整除的数。
比如2、3、5、7、11等都是素数。
要判断一个数n是否为素数,一种简单的方法是从2开始到√n进行遍历,判断是否存在能整除n的数。
如果存在,那么n就不是素数;如果不存在,则n是素数。
接下来,我们可以使用递归算法实现素数判定。
首先,我们编写一个辅助函数isDivisible(n, i),用于判断n是否能被i整除。
该函数返回一个布尔值,即True表示能整除,False表示不能整除。
然后,我们编写一个递归函数isPrime(n, i),用于判断n是否为素数。
该函数接收两个参数,n为待判定的数,i为当前的除数。
算法的基本思路是:- 如果n小于2,返回False,因为小于2的数都不是素数。
- 如果i大于√n,说明已经遍历完了所有可能的除数,返回True,即n是素数。
- 如果n能被i整除,返回False,即n不是素数。
- 如果n不能被i整除,递归调用isPrime函数,将i加1作为新的除数,继续判断。
最后,我们编写一个外部函数prime(n),调用isPrime函数来判断n 是否为素数,并返回相应的结果。
该函数是递归算法的入口。
以下是使用Python编写的递归算法判断素数的实现代码:```pythonimport mathdef isDivisible(n, i):if i == 1:return Falseif n % i == 0:return Truereturn isDivisible(n, i-1)def isPrime(n, i=2):if n < 2:return Falseif i > math.sqrt(n):return Trueif isDivisible(n, i):return Falsereturn isPrime(n, i+1)def prime(n):if isPrime(n):print(n, "是素数")else:print(n, "不是素数")#测试prime(7) # 输出:7 是素数prime(12) # 输出:12 不是素数```在这个实现中,isDivisible函数用于判断一个数n是否能被i整除。
判断素数的方法

判断素数的方法首先,最朴素的方法是试除法。
对于一个给定的数n,我们可以从2开始,依次用2、3、4、5……n-1来除以n,如果能够整除,则n不是素数;如果都不能整除,则n是素数。
这种方法的时间复杂度是O(n),并不是一个高效的方法,特别是在处理大数时,计算量会非常大。
因此,我们需要更高效的方法来判断素数。
其次,我们可以利用素数的性质来判断。
根据素数的定义,我们知道,如果一个数n不是素数,那么它一定可以被分解成两个因数a和b的乘积,即n=ab。
那么a和b中必定有一个小于等于√n。
因此,我们只需要判断2到√n之间的数是否能够整除n即可。
这种方法的时间复杂度是O(√n),相比于朴素的试除法,效率有了很大的提高。
除此之外,我们还可以利用素数的性质来进行判断。
根据费马小定理,如果p是一个素数,那么对于任意整数a,a的p次方减去a都能被p整除。
这就是费马小定理的内容。
因此,我们可以利用费马小定理来进行素数的判断。
这种方法在RSA加密算法中有着重要的应用。
另外,还有一种更高效的方法,即埃拉托斯特尼筛法。
这是一种用来查找一定范围内所有素数的算法。
其基本思想是从2开始,将每个素数的各个倍数都标记为合数。
这种方法的时间复杂度是O(nloglogn),是目前已知最高效的素数筛法。
总之,判断素数是一个数论中的重要问题,也是计算机算法中常见的问题之一。
本文介绍了几种常见的判断素数的方法,包括朴素的试除法、利用素数的性质、费马小定理和埃拉托斯特尼筛法。
希望能够帮助大家更好地理解和掌握素数的性质和判断方法。
同时,也希望大家能够在实际应用中灵活运用这些方法,解决相关问题。
用python求素数的25种方法和算法原理

用python求素数的25种方法和算法原理1.引言素数是只能被1和自身整除的正整数,具有重要的数论性质和在密码学、计算机科学等领域的应用。
本文将介绍用Py th on求解素数的25种方法和算法原理。
2.素数的定义和性质2.1素数的定义素数是指大于1的正整数,除了1和自身,不能被其他正整数整除的数。
2.2素数的性质-素数不可约:素数本身无法被其他数整除,因此无法分解成更小的因子。
-任意两个素数互质:素数之间没有公因数,除了1。
-无穷多个素数:素数的个数是无限的。
3.常见的素数判定方法3.1质数判定法质数判定法是最简单的方法,即逐个判断待测数是否被小于其平方根的正整数整除。
若不能整除,则待测数为素数。
d e fi s_pr im e(n):i f n<2:r e tu rn Fa ls ef o ri in ra ng e(2,int(n**0.5)+1):i f n%i==0:r e tu rn Fa ls er e tu rn Tr ue3.2费马素性测试费马素性测试利用费马小定理进行判定,基于二次剩余的概念,具有一定的准确性。
其原理是若a是素数,即a不被n整除,则a^(n-1)≡1(m od n)。
d e ff er ma t_te st(n,k=5):i f n==2:r e tu rn Tr uei f n%2==0or n==1:r e tu rn Fa ls ef o r_in ra ng e(k):a=ra nd om.r an di nt(1,n-1)i f po w(a,n-1,n)!=1:r e tu rn Fa ls er e tu rn Tr ue4.基于试除法的素数生成算法4.1埃拉托斯特尼筛法埃拉托斯特尼筛法(S i ev eo fE ra to st hen es)是一种简单高效的筛法,可以用于生成一定范围内的素数。
d e fp ri me s_er at ost h en es(n):p r im es=[]i s_p ri me=[Tr ue]*(n+1)i s_p ri me[0]=is_pr i me[1]=Fa ls ef o ri in ra ng e(2,int(n**0.5)+1):i f is_p ri me[i]:f o rj in ra ng e(i*i,n+1,i):i s_p ri me[j]=Fa lsef o ri in ra ng e(2,n+1):i f is_p ri me[i]:p r im es.a pp en d(i)r e tu rn pr im es5.其他高效的素数算法5.1线性筛法线性筛法(S ie ve ofE u le r)是一种不仅用于判定素数,还可以生成素数的算法。
素数的三种判断方法

素数的三种判断方法一、前言素数是指只能被1和它本身整除的正整数,也称为质数。
在数学中有着广泛的应用,例如在密码学、概率论等领域。
因此,判断一个数是否为素数是一个非常重要的问题。
本文将介绍三种判断素数的方法:试除法、埃氏筛法和米勒-拉宾素性检验。
二、试除法试除法是最简单直接的方法,即对于一个正整数n,从2到n-1依次进行试除,如果能被整除,则n不是素数;如果不能被整除,则n是素数。
代码实现:```bool isPrime(int n) {if (n < 2) return false;for (int i = 2; i < n; i++) {if (n % i == 0) return false;}return true;}```三、埃氏筛法埃氏筛法(也称为爱拉托逊斯筛法)是一种较快的判断素数的方法。
其基本思想是先将2到n之间的所有整数标记为素数,然后从2开始,将每个素数的倍数都标记为合数。
最终未被标记为合数的数字即为素数。
代码实现:```bool isPrime(int n) {if (n < 2) return false;bool is_prime[n+1];memset(is_prime, true, sizeof(is_prime));for (int i = 2; i <= sqrt(n); i++) {if (is_prime[i]) {for (int j = i * i; j <= n; j += i) {is_prime[j] = false;}}}return is_prime[n];}```四、米勒-拉宾素性检验米勒-拉宾素性检验是一种基于费马小定理的概率算法,可以用于判断一个数是否为素数。
其基本思想是:对于一个奇数n,如果存在一个整数a,使得$a^{n-1} \not\equiv 1 \pmod{n}$且$a^{\frac{n-1}{2}} \not\equiv -1 \pmod{n}$,则n不是素数。
素数检测算法

素数检测的几种算法素数,又称质素,除了能表示为它本身和1的乘积以为,不能表示为任何其它两个整数的乘积。
一、试除法根据素数的定义,假设要判断的自然数为n,那么最简单的方法便是用2~(n-1)之间的数字依次枚举试除一遍,如果能整除,那说明这个数不是素数,显然,此种算法的效率极低。
初学C语言的人会使用另一种改进的试除法,那便是除数不用取遍2~(n-1),而是取2~(int)sqrt(n),但是当n很大时,此种算法的时间消耗也很大,也是不可取的。
二、筛选法筛选法事一种比较高校的判断素数的方法,能够一次性的筛选除某个区间的素数。
算法的基本原理也是利用了素数的定义,在某个范围内,依次去掉2的倍数,3的倍数,5的倍数……以此类推,一直到所有小于或等于n的数字的倍数都被去掉为止。
这就像一面筛子,把某个区间范围内满足条件的数留下来,其余的数字去掉,最后判断此区间内的某个数是否为素数时,时间复杂度就为O(1)。
很显然,时间的主要消耗都在于数字的筛选上。
利用给数组单元置零的方法来实现,创建一个数组a[i],i=1、2、3……,用memset()函数将其全部置1,当i不是素数,则将a[i]置零。
代码实现如下:#define MAX N /*N为设置的某个数,确定一个判断区间*/int isprime[MAX];void is_prime1(){int i,j;memset(isprime,1,sizeof(isprime));for(i=2;i<MAX;i++){if(isprime[i])for(j=2*i;j<MAX;j+=i)isprime[i]=0;}}此种筛选算法可以优化为二次筛选,就是要求n以内的素数,就先把sqrt(n)内的素数求出来,再用已经求得的素数来筛选后面的合数。
2007年,复旦的xreborner将筛选法进一步改进为真正的线性时间复杂度,改进算法是增加了一个数组,记录已经找到的素数,通过这些已经找到的素数,来筛掉后面的数。
判断素数的算法

判断素数的算法
一个正整数如果只能被1和它本身整除,那么它就是素数。
判断素数的算法有以下几种:
1.试除法:从2开始,依次判断该数能否被2、3、4、……、它本身-1整除,如果都不能整除,那么该数就是素数。
但是该算法效率不高,对于大数不太适用。
2.厄拉多塞筛法:首先将2到n的自然数列出来,然后把2的倍数筛掉(除2以外),把3的倍数筛掉(除3以外),把4的倍数筛掉(除4以外),以此类推,直到筛不出任何数为止。
剩下的所有数就都是素数了。
该算法效率较高。
3.米勒-拉宾素性检验(Miller-Rabin Primality Test):该算法借助费马小定理,通过若干次随机检验判断一个数是否为素数,其效率为O(k log^3 n),其中k 为检验次数。
该算法适用于大数的判断。
还有其他一些算法,比如Baillie-PSW素性检验、AKS测试等,但是这些算法涉及到高级数学知识,不太容易理解。
判断素数方法

判断素数方法
判断素数的方法有很多种,以下是其中几种常见的方法:
1. 试除法:从2开始,依次尝试将2、3、4、5、6...整除,如果
整除后的结果大于1,那么这个数就不是素数。
如果每次都能够整除,说明这个数是素数。
2. 埃氏筛法:从2开始,依次将每个数添加到列表中,然后把每
个数从列表中删除,重复这个过程直到列表中的数只剩下1和它本身。
如果列表中只剩下1和它本身,那么这个数就是素数。
3. 费马小定理:对于大于2的任何整数n,p(n)%n=1,其中p是小于等于n的素数。
这个定理可以用来判断素数p的取值范围。
4. 米勒-拉宾素性测试:类似于费马小定理,米勒-拉宾素性测试
也是对于大于2的任何整数n,判断p(n)是否是n的因数。
它的优点
是可以在不需要太多计算的情况下判断素数p的取值。
以上是几种常见的判断素数的方法,具体方法选择应根据实际情
况和需要进行。
C语言判断素数(求素数)(两种方法)

C语言判断素数(求素数)(两种方法)素数又称质数。
所谓素数是指除了 1 和它本身以外,不能被任何整数整除的数,例如17就是素数,因为它不能被 2~16 的任一整数整除。
思路1):因此判断一个整数m是否是素数,只需把 m 被 2 ~ m-1 之间的每一个整数去除,如果都不能被整除,那么 m 就是一个素数。
思路2):另外判断方法还可以简化。
m 不必被 2 ~ m-1 之间的每一个整数去除,只需被 2 ~ 之间的每一个整数去除就可以了。
如果 m 不能被 2 ~ 间任一整数整除,m 必定是素数。
例如判别 17 是是否为素数,只需使 17 被 2~4 之间的每一个整数去除,由于都不能整除,可以判定 17 是素数。
原因:因为如果 m 能被 2 ~ m-1 之间任一整数整除,其二个因子必定有一个小于或等于,另一个大于或等于。
例如16 能被 2、4、8 整除,16=2*8,2 小于 4,8 大于 4,16=4*4,4=√16,因此只需判定在 2~4 之间有无因子即可。
两种思路的代码请看解析。
思路1) 的代码:#include <stdio.h>int main(){int a=0; // 素数的个数int num=0; // 输入的整数printf("输入一个整数:");scanf("%d",&num);for(int i=2;i<num;i++){if(num%i==0){a++; // 素数个数加1}}if(a==0){printf("%d是素数。
\n", num);}else{printf("%d不是素数。
\n", num);}return 0;}思路2)的代码:#include <stdio.h>#include <math.h>void main(){int m; // 输入的整数int i; // 循环次数int k; // m 的平方根printf("输入一个整数:");scanf("%d",&m);// 求平方根,注意sqrt()的参数为 double 类型,这里要强制转换m的类型k=(int)sqrt( (double)m );for(i=2;i<=k;i++)if(m%i==0)break;// 如果完成所有循环,那么m为素数// 注意最后一次循环,会执行i++,此时 i=k+1,所以有i>kif(i>k)printf("%d是素数。
数论中的素数测试算法

数论中的素数测试算法数论是研究数与数之间的关系和性质的学科,素数测试算法是指判断一个数是否为素数的方法。
在密码学、计算机科学等领域中,素数测试算法有着广泛的应用。
本文将介绍三种常见的素数测试算法——试除法、费马小定理和米勒-拉宾素性检验。
一、试除法试除法是素数测试中最简单的一种方法。
假设a是一个数,则如果a能被2~a-1之间任何一个数整除,那么a就不是素数。
否则,a就是素数。
试除法虽然简单,但对于大数来说,需要枚举很多数,计算量很大,所以不适用于大数的素数测试。
例如:判断7是否是素数。
试除法枚举2~6之间的数,发现这些数都不能整除7,因此7是素数。
二、费马小定理费马小定理是一种基于模运算的素数测试方法。
费马小定理的内容为:若p是素数,a是正整数,则a ^ (p-1) ≡ 1 (mod p)。
该定理的逆定理不成立,即对于一个合数,可能满足a ^ (n-1)≡ 1(mod n)。
因此,可以采用费马小定理来判定某个数是否为素数的概率,但有概率判断错误。
例如:判断17是否是素数。
计算2 ^ 16(mod 17),结果为1,因此17很可能是素数。
三、米勒-拉宾素性检验米勒-拉宾素性检验是应用最广泛和最有效的一种素数测试算法,被认为是一种强素数测试,可以高效快速地判断一个数字是否为素数。
其基本思想是利用费马小定理的逆定理,即p是一个素数,则a ^ (p-1) ≡ 1 (mod p)。
反过来,根据费马小定理,若满足a ^ (p-1)≡ 1 (mod p),p也可能是素数。
米勒-拉宾素性检验的步骤如下:1、将n-1表示成2^s * d的形式,其中s>=1,d是奇数。
2、随机选取一个a,使得1 < a < n-1。
3、计算a^d mod n,如果等于1,或者等于n-1,则可能是素数,进行下一次测试。
4、若a^d mod n不等于1也不等于n-1,则重复平方d,即d =2 * d,继续计算a^d mod n。
求1到n素数

int i,j; i=2; cout<<i<<"\t"; for(i=3;i<=n;i+=2) {
for(j=3;j<i;j+=2) {
if(i%j==0)//判断是否能整除; {
break; } } if(j==i)//判断是否是素数; cout<<i<<"\t";//输出所求的素数; } }
int main() {
int num; cout<<"请输入整数 num:"; cin>>num; cout<<"这是求 2—"<<num<<"之间的素数的程序\n"; primenumber(num); cout<<endl; return 0; } 方法四: #include<iostream> #include<cmath> using namespace std;
3、示例程序
方法一: #include<iostream> using namespace std;
void primenumber(int n) {
int i,j; for(i=2;i<=n;i++) {
for(j=2;j<i;j++) {
if(i%j==0)//判断是否能整除; {
break; } } if(j==i)//判断是否是素数; cout<<i<<"\t";//输出所求的素数; }
ift条件判断素数

ift条件判断素数一、什么是素数?素数,也叫质数,指的是大于1的自然数中,除了1和自身之外没有其他因数的数。
换句话说,素数只能被1和它本身整除,不能被其他数整除。
二、判断素数的方法判断一个数是否为素数有多种方法,下面将介绍其中两种常见的方法。
1.试除法试除法是最基本的判断素数的方法。
对于一个大于1的自然数n,我们从2开始,依次判断n能否被2、3、4、5、6、...、n-1整除。
如果n能被其中任意一个数整除,那么它就不是素数;如果n不能被任何一个数整除,那么它就是素数。
例如,我们要判断数13是否为素数,我们从2开始,依次判断13能否被2、3、4、5、6、7、8、9、10、11、12整除。
我们可以发现13不能被2、3、4、5、6、7、8、9、10、11、12整除,因此13是素数。
试除法的时间复杂度为O(n),其中n是待判断的数。
它是一种简单直观的方法,但对于大数来说,效率比较低。
2.开方法开方法是一种优化的判断素数的方法。
我们知道,如果一个数n不是素数,那么它一定可以被2到√n之间的某个数整除。
因此,我们只需要判断n是否能被2到√n之间的数整除即可。
例如,我们要判断数13是否为素数,我们只需要判断13能否被2、3、4、5、6、7整除,因为√13约等于3.6,所以我们只需要判断13能否被2、3整除即可。
开方法的时间复杂度为O(√n),它比试除法的效率高很多。
在实际应用中,开方法是常用的判断素数的方法。
三、应用场景判断素数在计算机科学中有着广泛的应用。
例如,在密码学中,素数被广泛用于生成安全的公钥和私钥。
素数还被应用于数据压缩算法中。
在一些压缩算法中,素数被用来作为哈希表的大小,以提高数据压缩的效率。
判断素数的方法也经常被用于算法竞赛中的题目,考察选手对数学和算法的理解和运用能力。
总结:判断素数是一个重要的数学问题和计算机科学中常见的算法之一。
本文介绍了判断素数的两种常见方法:试除法和开方法。
试除法是最基本的方法,开方法是一种优化的方法,效率更高。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
求素数列表和判断素数的算法有兴趣阅读本文的读者,应该对素数概念是十分熟悉的了。
用计算机程序实现素数计算,集中在2个主要问题上:∙判断一个正整数是否是素数-(算法A)∙求一定范围内的素数列表- (算法B)关于素数的算法,根据素数的数学性质,大家都会想到如下几个方面:∙用遍历求模的方式判断素数∙素数都是奇数,可以在奇数数列中寻找素数∙利用开方来缩小搜索的范围然后,求素数的计算是复杂的,如果算法写得不好,则耗时较高。
在百度百科“素数”条目中的算法程序,是值得商榷的。
很多方法是O(N2)的算法。
为此,在本文中探讨了求素数列表和判断素数这两个算法,力图使算法可以达到O(N Log(N))优化级别。
在本文中,算法语言选用C#。
1,判断素数的简单实现(算法A-1)///<summary>///算法A-1,判断素数///</summary>///<param name="number">待测正整数</param>///<returns>是否为素数(为了简化,1以下的整数皆为素数)</returns>public static bool IsPrime(int number){// 为了简化,1以下的整数皆为素数if(number <= 2){return true;}// 奇偶性if (number % 2 == 0){return false;}// 利用开方缩小范围,优化效果十分明显int range = (int)Math.Sqrt(number) + 1;// 从3开始的奇数列for (int current = 3; current <= range; current += 2){// 判断是否为素数if (number % current == 0){// 合数return false;}}return true;}A-1算法中,首先判断奇偶性,再判断从3开始判断待查数(number)是否是合数,若到Math.Sqrt(number)还没有查到是合数,即为素数。
这个方法是O(N1/2)级别的算法,所以很快,即使是最悲观的int.MaxValue,在本人的本机计算也可达到125ms的运行时间。
2,判断素数的优化算法(A-2)虽然这种算法速度比较快,但如果频繁使用A-1算法,累计起来开销就比较大了,假设有N次访问的话,算法级别就到了O(N3/2)。
因此,本人的解决方案是先计算出一定范围内的素数列表存放在哈希表中,多次调用就可以忽略查询时间了。
///<summary>///素数的Hash表///</summary>private static HashSet<int> Primes { get; set; }///<summary>///算法A-2,判断素数///</summary>///<param name="number">待测正整数</param>///<returns>是否为素数(为了简化,1以下的整数皆为素数)</returns>public static bool IsPrime2(int number){// 为了简化,1以下的整数皆为素数if (number <= 2){return true;}return Primes.Contains(number);}这种算法的前提是要求一个素数表,这就是算法B要研究的问题了。
3 求素数列表的简单算法(B-1)///<summary>///求素数列表的简单算法(算法B-1)///</summary>///<param name="range"></param>///<returns></returns>public static int[] GetPrimes(int range){List<int> primeList = new List<int>();// 从3开始的奇数列for(int current = 3; current <= range; current += 2){// 判断是否为素数bool isPrime = true;foreach (int prime in primeList){if (current % prime == 0){// 若为合数,进入下一数的判断isPrime = false;break;}}if (isPrime){// 加入素数列表primeList.Add(current);}}// 把2补入primeList.Insert(0, 2);return primeList.ToArray();}上述算法,是对小于N的数,遍历素数表,判断是否为合数,全不成立的即为素数,并加入素数表。
这个算法的一个特点是只对奇数数列进行遍历,从而使遍历次数减少了一半。
4,步长优化的算法(算法B-2)有读者会想到阴阳素数数列的问题,也就是除了2,3以外,素数要么在(6N-1)数列,要么在(6N+1)数列,这样,是不是就可以通过改变步长方式就可以提高速度?是的,本人也做过这样的实验,代码如下:///<summary>///求素数列表的简单算法(算法B-2)///</summary>///<param name="range"></param>///<returns></returns>public static int[] GetPrimes2(int range){List<int> primeList = new List<int>();int index = 1; // 步长下标int[] loops = new int[] { 2, 4 };//步长for (int current = 5; current <= maxValue; current += loops[index]) {// 判断是否为素数bool isPrime = true;foreach (int prime in primeList){if (current % prime == 0){// 若为合数,进入下一数的判断isPrime = false;break;}}if (isPrime){// 加入素数列表primeList.Add(current);}index ^= 1; //阴阳数列转换}// 把2,3补入primeList.Insert(0, 2);primeList.Insert(0, 3);return primeList.ToArray();}采用步长数组和异或操作切换,可以最大限度的不增加代码优化后的开销。
这样的优化取得了一定的优化效果,但效果不明显。
我分析,B-1是最多达到了50%的优化,而B-2是达到了33.3%的优化效果,所以优化不明显。
所以后面的算法,就忽略了B-2的这样的优化。
5,采用开方法优化的算法(算法-B-3)本文的重点来了求素数列表的一大挑战,是当求解的范围很大时,速度就会变得其慢。
在对int.MaxValue/ 10000规模计算中,大致是1910ms左右,在往上速度就很慢了。
分析原因,算法中的最大的瓶颈在于求模操作。
由于求模操作命中率不高,所以执行次数很多。
根据数论知识,可以得到下来推论:把全集X = {n|n <= N}, 可以分为两个子集,X1={n | n <= N1/2 + 1}和X2={n | N1/2 + 1 < n <=N}, Y1是X1中的素数子集, Y2是X2中的素数子集,则X2中的所有合数的因数,全属于Y1。
(推论-1)这个推论告诉我们,我们可以把算法分成两部分,按B-1方法求1到 N1/2 + 1部分的素数(Y1),在把N1/2 + 1到N的数求模一次求素数(而不是遍历素数表),得到Y2,Y1+Y2就是全部素数表。
///<summary>///平方法(算法B-3)///</summary>///<returns></returns>public static int[] GetPrimes3(int maxValue){int range = (int)Math.Sqrt(maxValue);// 素数列表List<int> primeList = new List<int>();int current = 3;// 从3开始的奇数列for (; current <= range; current += 2){// 判断是否为素数bool isPrime = true;foreach (int prime in primeList){if (current % prime == 0){// 若为合数,进入下一数的判断isPrime = false;break;}}if (isPrime){// 加入素数列表primeList.Add(current);}}List<int> primeList2 = new List<int>();// 从3开始的奇数列for (; current <= maxValue; current += 2){// 判断是否为素数bool isPrime = true;foreach (int prime in primeList){if (current % prime == 0){// 若为合数,进入下一数的判断isPrime = false;break;}}if (isPrime){// 加入素数列表primeList2.Add(current);}}// 把2补入primeList.Insert(0, 2);primeList.AddRange(primeList2);return primeList.ToArray();}这样的修改将使运行效率提高了近100倍。
6,利用筛法进行更高级的优化(算法B-4)对于上述用例,主要对19980个素数的二次循环上,在从N1/2到N之间的数中,进行log(M1)的循环(基数是623)和求模。
所以这个算法的复杂度是O(log(M1)*(N- N1/2))。