前言:本文主要求讲解求不大于N的数的质数个数方法。
方法一:暴力循环(效率较低,但容易理解)
一个数如果是质数,则对从2开始到它的前一个数取余均不会是0,因此直接暴力循环即可。
public static void test1(int n){
int num=0;
boolean sign;
for(int i=2;i<n;i++){
if(i % 2 == 0 && i != 2 ) continue; //偶数和1排除
sign=true;
for (int j=2;j<i;j++){
if(i%j==0){
sign=false;
break;
}
}
if (sign){
num++;
}
}
System.out.println(n+"以内的素数有"+num+"个");
}
方法二:显然,我们只需要检查到不大于N/2 的数即可,后面的数不可能取余为0,因此我们可以把遍历范围缩小为方法一的一半。
public static void test2(int n){
int num=0;
boolean sign;
for(int i=2;i<(n/2);i++){
if(i % 2 == 0 && i != 2 ) continue; //偶数和1排除
sign=true;
for (int j=2;j<i;j++){
if(i%j==0){
sign=false;
break;
}
}
if (sign){
num++;
}
}
System.out.println(n+"以内的素数有"+num+"个");
}
方法三:把遍历的边界缩小到sqrt(N)。效率再次加快!
因为如果一个数不是素数是合数,那么一定可以由两个自然数相乘得到,其中一个大于或等于它的平方根,一个小于或等于它的平方根。并且成对出现,所以只用计算到该数的平方根以下看除了1有没有该数的因数,若没有,则是素数。
public static void test3(int n){
int num=0;
boolean sign;
for(int i=2;i<(n/2);i++){
if(i % 2 == 0 && i != 2 ) continue; //偶数和1排除
sign=true;
for (int j=2;j<i;j++){
if(i%j==0){
sign=false;
break;
}
}
if (sign){
num++;
}
}
System.out.println(n+"以内的素数有"+num+"个");
}
方法四:埃氏筛选法(这里有一篇很详细的文章,大家可以去看看埃氏筛选法)
埃拉托斯特尼筛法,简称埃氏筛或爱氏筛,是一种由希腊数学家埃拉托斯特尼所提出的一种简单检定素数的算法。要得到自然数n以内的全部素数,必须把不大于根号n的所有素数的倍数剔除,剩下的就是素数。
例子:
给出要筛数值的范围n,找出以内的素数。先用2去筛,即把2留下,把2的倍数剔除掉;再用下一个质数,也就是3筛,把3留下,把3的倍数剔除掉;接下去用下一个质数5筛,把5留下,把5的倍数剔除掉;不断重复下去……。
![](https://i-blog.csdnimg.cn/blog_migrate/6632a8db3f43a1e4451165f24cdec260.gif)
代码实现如下:
//求0~n-1的质数个数(埃氏筛选法)
public static int getSum(int n){
int sum=0;
int[] arr=new int[n];
arr[0]=1;
arr[1]=1;
boolean flag;
int now=2;
while(now<n){
for (int i = now+now; i < n; i+=now) {
arr[i]=1;
}
flag=false;
for (int i = now+1; i < n; i++) {
if(arr[i]==0){
now=i;
flag=true;
break;
}
}
if(!flag){
break;
}
}
for (int i = 0; i < n; i++) {
if(arr[i]==0)sum++;
}
return sum;
}