一、试除法
求一个数是否是质数,遍历就行
二、朴素筛法
求2~n中有多少个数是质数
一个合数必定能分解为, 一个质数乘以 一个质数/合数。所以我们将 2~n 的所有质数 的倍数删掉,那么这个数组的所有合数就被删除了,剩下的就是质数。
三、线性筛法
求2~n中有多少个数是质数
线性筛法 求2~n中有多少个质数,朴素筛法 有冗余的筛除,而线性筛法就是解决掉了,这问题,它的思想就是,用一个数的最小质数去筛掉该数,就不会导致重复筛一个数
四、代码
package cource.nemberTheory;
import java.util.Arrays;
/**
* @Auther: duanYL
* @Date: 2023/10/17/9:17
* @Description:
*/
public class Prime {
public static void main(String[] args) {
System.out.println(isPrime(20));
getPrimes(20);
obtainPrimes(20);
}
/**
* 试除法求单个质数
*/
public static boolean isPrime(int target) {
if (target < 2)
return false;
/* 这里不建议使用i*i,可能会越界.
也不建议使用Math.sqrt(target),直接除,编译器可以优化
*/
for (int i = 2; i <= target / i; i++) {
if (target % i == 0)
return false;
}
return true;
}
/**
* 朴素筛法求 2~n中有多少个质数
* 一个合数必定能分解为 一个质数乘以 一个质数/合数
* 所以我们将 2~n 的所有质数 的倍数删掉
* 那么这个数组的所有合数就被删除了
* 剩下的就是质数
*
* @param n
*/
public static void getPrimes(int n) {
int count = 0; //记录有多少个素数
int[] primes = new int[n + 1]; //记录素数
/*
boolean数组默认值为false,为false为质数,true为合数
*/
boolean[] st = new boolean[n + 1];
for (int i = 2; i <= n; i++) {
if (st[i])
continue;
primes[count++] = i;
/* 第二个循环不难看出会有 冗余的筛除
当i为2时,st[2]=true,st[4]=true,st[6]=true
当i为3时,st[3]=true,st[6]=true
st[6]重复筛了一次
*/
for (int j = i; j <= n; j += i) { //将当前质数的所有倍数筛除
st[j] = true;
}
}
System.out.println(Arrays.toString(Arrays.copyOf(primes, count)));
}
/**
* 线性筛法 求2~n中有多少个质数
* 朴素筛法 有冗余的筛除,而线性筛法就是解决掉了,这问题
* 它的思想就是,用一个数的最小质数去筛掉该数,就不会导致重复筛一个数
*
* @param n
*/
public static void obtainPrimes(int n) {
int count = 0; //记录有多少个素数
int[] primes = new int[n];
boolean[] st = new boolean[n + 1]; //为false为质数,true为合数
for (int i = 2; i <= n; i++) {
if (!st[i]) //如果是质数则记录
primes[count++] = i;
for (int j = 0; primes[j] <= n / i; j++) {
st[primes[j] * i] = true; //primes[j]是primes[j] * i的最小的质数
if (i % primes[j] == 0)
break;
}
}
System.out.println(Arrays.toString(Arrays.copyOf(primes, count)));
}
}