[英]Count prime number till N
这段代码可以很好地计算素数直到 n。 问题是当 n 值大到 1000000 或更多时,执行和打印输出需要很长时间(超过 30 秒)。 我想解决这个问题。 任何帮助都会很棒。 下面是代码:
public class PrimeNotillN {
public static void main(String[] args) {
int n = 1000;
int count = 0;
for (int i = 2; i < n; i++) {
boolean res = checkprime(i);
if (res == true)
count++;
}
System.out.println("total prime number till " + n + " is " + count);
}
private static boolean checkprime(int n) {
if (n == 1)
return false;
else {
for (int i = 2; i <= n / 2; i++) {
if (n % i == 0) {
return false;
}
}
return true;
}
}
}
做最简单的变化是结束for
在循环checkprime
后, i
已经达到的平方根n
。 原因是如果你发现一个因子大于n
平方根,那就意味着有一个因子小于应该已经找到的n
平方根。
for (int i = 2; i <= Math.sqrt(n); i++) {
此外,如果您需要更高的速度,将所有素数打印到最大限度的最佳算法是Eratosthenes的Sieve 。 这涉及到取代你拥有的东西。 你需要一个数组,你可以在其中标记哪些数字是复合数。 从2开始,您将所有2的倍数标记为复合。 在数组中移动,如果您找到一个未标记为复合的数字,则它是素数,您可以打印它。 对于您遇到的每个素数,您将所有素数的倍数标记为复合。
除了2之外,素数从来都不是。 Primes只能被1和iteslef整除。
你也可以查看它的sqrt。 如果你什么都没发现那么它就是一个素数。
public bool IsPrime(double num)
{
bool isprime = true;
double limit = Math.Sqrt(num);
if (num % 2 == 0)
return num == 2;
if (num == 3 || num == 5 || num == 7)
return true;
for (int i = 3; i < limit; i++)
if (num % 1 == 0)
return false;
return isprime;
}
Eratosthenes 筛法是一种非常著名且高效的算法,可以生成大约 1-1000 万个小素数。 这是一个古老的算法,由一位名叫 Eratosthenes 的希腊数学家给出。
public class CountPrimes {
public static void main(String[] args) {
System.out.println(countPrimes(1000000));
}
public static int countPrimes(int n) {
boolean[] primes = new boolean[n +1];
for(int i = 0 ; i <= n ; i++) {
primes[i] = true;
}
primes[0] = false;
primes[1] = false;
for(int i = 2 ; i * i <= n ; i++) {
if(primes[i]) {
for(int j = i ; i * j <= n ; j++) {
primes[j * i ] = false;
}
}
}
int primeCounts = 0;
for(int i = 2 ; i <= n ; i++) {
if(primes[i]) {
primeCounts++;
}
}
return primeCounts;
}
}
您可以将找到的素数存储到列表中,并仅对它们进行进一步检查(Sieve of Eratosphenes):
import java.util.ArrayList;
import java.util.List;
public class PrimeNotillN {
public static void main(String[] args) {
int n = 1000000;
int count = 0;
List<Integer> primes = new ArrayList<>();
for (int i = 2; i < n; i++) {
boolean res = checkprime(primes, i);
if (res) {
count++;
primes.add(i);
}
}
System.out.println("total prime number till " + n + " is " + count);
}
private static boolean checkprime(List<Integer> primes, int n) {
int fence = (int) Math.sqrt(n);
for (int prime : primes) {
if (n % prime == 0) {
return false;
}
if (prime >= fence)
break;
}
return true;
}
}
使用eratoshtenes方法的筛子并保持所有素数的缓存
public int countPrimes(int n) {
if(n==0){
return 0;
}else{
boolean[] isPrime=new boolean[n];
for(int i=2;i<n;i++){
isPrime[i]=true;
}
for(int i=2;i*i<n;i++){
if(!isPrime[i]){
continue;
}
for(int j=i*i;j<n;j+=i){
isPrime[j]=false;
}
}
int counter=0;
for(int i=2;i<n;i++){
if(isPrime[i]){
counter++;
}
}
return counter;
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.