我正在使用Java中的方法来创建布尔数组 isPrime :
boolean[] isPrime;
其中素数标有' true'其余的是“假”' 虽然我在这里,但我也想计算一下Primes的数量:
int numPrimesFound;
基本思想是使用Eratosthenes的Sieve。到目前为止,我的方法看起来像这样:
public Sieve(final int limit) {
long startTime = System.currentTimeMillis();
boolean[] isPrime = new boolean[limit];
this.isPrime = isPrime;
for (int i=3; i<=limit ;i+=2) {
isPrime[i] = true; //sets all even numbers to true
}
isPrime[2] = true;
numPrimesFound = 1; //special case of '2'
for (int i = 3; i * i <= limit; i += 2) {
if (isPrime[i] == true) {
for (int j = i; i * j <= limit; j += 2) {
isPrime[i * j] = false; //has a multiple ==> not a prime
numPrimesFound++; //doesn't work yet
}
}
}
long stopTime = System.currentTimeMillis(); //measuring execution time
System.out.println("Sieve: " + (stopTime - startTime) + " milliseconds.")
}
所以我的问题是那个
numPrimesFound++:
不起作用,因为筛子将某些非素数的值设置为“假”和“假”。 不止一次(例如45 bcs 3 * 15 = 45,9 * 5 = 45)。
所以有人知道我如何重写这个程序,所以它将所有非素数设置为“假”&#39; 只有一次?
或者一般来说,任何人都可以提出使方法更快的方法吗?
答案 0 :(得分:1)
如果您使用BitSet
,可以请求cardinality
。
public BitSet primes(final int limit) {
long startTime = System.currentTimeMillis();
BitSet isPrime = new BitSet(limit);
// A bitSet starts all zeros but with a sieve - evrything must start prime.
isPrime.flip(0, limit);
// 0 and 1 are not prime
isPrime.clear(0);
isPrime.clear(1);
for (int i = 2; i * i <= limit; i += 2) {
if (isPrime.get(i)) {
// Remove all multiples of i.
for (int j = 2; i * j <= limit; j += 1) {
isPrime.clear(i * j);
}
}
}
long stopTime = System.currentTimeMillis(); //measuring execution time
System.out.println("Sieve: " + (stopTime - startTime) + " milliseconds.");
return isPrime;
}
public void test() {
BitSet primes = primes(50);
System.out.println("Primes: " + primes);
System.out.println("Count: " + primes.cardinality());
}
我还修复了你逻辑中的一些错误。例如。你的内循环是由j
踩2
而你的外循环没有移除所有偶数(从3
开始)。
你当然可以改进这一点 - 谷歌是你的朋友。 :)
答案 1 :(得分:1)
这是我的版本:
import java.util.BitSet;
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.println("Enter the interval limit: ");
int limit = sc.nextInt();
int max = (int) Math.sqrt(limit);
long start = System.currentTimeMillis();
BitSet intArray = new BitSet(limit);
// 1 is not prime
intArray.set(0);
// 2 is the first prime number, so the first step is to filter out all even numbers
for (int i = 2; (2 * i) - 1 < limit; i++) {
intArray.set((2 * i) - 1);
}
//all remaining number will be odd
int currentNumber = 3;
// i is the multiplicator and will be adjusted with the current number , in order to avoid repetition
int i = 3;
int temp;
while (currentNumber <= max) {
// flag multiple of the current prime number
do {
temp = (currentNumber * i);
if (temp > limit) break;
intArray.set(temp - 1);
i = i + 2;
} while (temp <= limit);
//all non-prime numbers until now are already flagged, therefore we can find the next prime number by checking the set-status.
while (currentNumber + 2 <= limit) {
currentNumber += 2;
if (!intArray.get(currentNumber - 1)) {
i = currentNumber;
break;
}
}
}
int b = 0;
for (int n = limit -1 ; n > 0; n--){
if (!intArray.get(n)){
b = n +1;
break;
}
}
System.out.println("There are " + (limit - intArray.cardinality()) + " PRIMES and the biggest is: " + b);
System.out.println("Time in total: " + ((System.currentTimeMillis() - start) / 1000.0) + "s");
}
}
要检查100 mio数字,需要大约我的i7 3770k台式电脑上的0,7秒。
答案 2 :(得分:0)
你有一个困惑:
numPrimesFound ++;没关系,但它必须在循环之外(int j = i; i * j&lt; = limit; j + = 2)
你的主循环必须走得更远(或者你忘记了大于sqrt(极限)的素数
expire_dns_cache
在Eratosthenes Sieve中,通常会标记几次&#34;非素数&#34;号。
和i * j&lt;如果变得大于int(它变为负数),则极限为NOK
结果就是这样,但只有
for (int i = 3; i < limit; i += 2)
用你替换你的内循环,你至少可以去1000000
final int limit=40000; // 50 000 is too big !
你可以使用bitset
答案 3 :(得分:0)
好的..这就是我想出来的
long startTime = System.currentTimeMillis();
int limit = 100000;
boolean[] isPrime = new boolean[limit+1];
Arrays.fill(isPrime, true);
isPrime[0] = false;
isPrime[1] = false;
int numPrimesFound = limit-1;
System.out.println("Sqrt is:" + Math.sqrt(limit));
for (int i=2; i < Math.sqrt(limit);i++) {
if (isPrime[i] == true) {
int inc = 0;
while (true) {
int j = (i*i) + (inc*i);
if( j > limit) break;
if (isPrime[j]) {
isPrime[j]= false;
numPrimesFound--;
}
inc++;
}
}
}
System.out.println("Number of Primes" + numPrimesFound);
for (int i = 2; i < limit;i++) {
if (isPrime[i])
System.out.println("Prime#:" + i);
}
long stopTime = System.currentTimeMillis(); //measuring execution time
System.out.println("Sieve: " + (stopTime - startTime) + " milliseconds.");