一、最简单的方法
从2到n-1进行遍历
对n进行质数判断,质数的定义为该数除了1和其本身在无其他的因数。因此对n进行除i操作,i的范围为2到n-1,如果可以除尽,则表示n除了1和其本身还有其他的因数,因此n不是质数,返回false,如果在除以i的时候并没有除尽的操作,则返回true。
public boolean method1(String [] args){
int n=10;
for(int i=2;i<n;i++){
if(n%i==0)
return false;
}
return true;
}
从2到n/2
上面的方法思想简单,但是效率比较低,很多数会重复进行除操作,所以将i的范围缩小到2--n/2,可以提高效率。
public boolean method2(String [] args){
int n=10;
for(int i=2;i<=n/2;i++){
if(n%i==0)
return false;
}
return true;
}
从2到Math.sqrt(n)进行遍历
该方法和上面的方法的意图是相同的,该方法将i的范围缩小到2---Math.sqrt(n)
public boolean method3(String [] args){
int n=10;
for(int i=2;i<=Math.sqrt(n);i++)
//for(int i=2;i*i<=n;i++) //和上一行的代码意思相同
{
if(n%i==0)
return false;
}
return true;
}
第一种方法思想简单,但是效率不高,尤其是在求n以内的质数这种题上。
二、埃及筛
认真看喽,本文重点来啦
1、概念:
一个素数的整数倍必定为合数
2、算法的思想
1、创建一个长度为n+1的数组prim; //我当时一直想不明白为什么要创建一个n+1长度的数组,判断的数为n,难道不应该创建数组的长度为n吗?(不知道有没有人和我一样呢?哈哈哈)
后来我才想明白因为数组的下标是从0,开始的,若n=10,你创建一个长度为n的数组,数组是从0--9的,并不包含10。
2、初始化prim数组的所有元素都为1,即默认所有的数都是质数;
3、进入for循环,进行判断;此时范围为for(int i=2;i<=n;i++);// i从2开始,是因为数组中下标为0的数用不上,下标为1的数是用来表示数字1的,而1不是质数,所以要从数字2进行判断;
4、在for循环中,如果prim[i]==1(i为质数),则将i的所有整数倍置为合数。此时本来是要对所有的i(质数)都要进行整数倍置为合数的操作,但是这样不仅效率比较低,而且越往后置为合数的数越少,所以这里让i只到Math.sqrt(n); 对i进行整数倍置为合数操作的时候,本应该 2i 3i 4i......都要置为合数的,但是有些数在之前的i-1已经操作过,所以此时不必在进行操作,我们只需要从i*i开始即可。举个例子
i=2,prim[i]==1---->if(i*i<=n)---->4 6 8 10都置为合数
i=3,prim[i]==1---->if(i*i<=n)----->6 9置为合数,可此时6已经操作过了,所以我们应从i*i开始操作
3、代码
public boolean method4(){
int n=10;
int [] prim=new int[n+1];//创建一个长度为n+1的数组
Arrays.fill(prim,1);//初始化所有的数都为质数,用1表示为质数,0表示为合数
//Arrays.fill(int [],int val)函数:将指定的 int 值分配给指定 int 型数组的每个元素
for(int i=2;i<=n;i++){
if(prim[i]==1){ //如果i为合数
if(i*i<=n) //对i到MAth.sqrt(i)进行判断
for(int j=i*i;j<=n;j+=i) //从i*i开始进行置为合数操作,步长为i
prim[j]=0;
}
}
return prim[n]==1?true:false;
}