I wanted to try and use the Sieve of Eratosthenes to find all prime numbers between some arbitrary bounds 1 <= m <= n. The simple implementation of the sieve does not consider the lower bound at all, it always starts from 1 (or actually from 2). So for a big enough n, simply creating an array would be impossible.
The algorithm first finds all prime numbers from 1 to sqrt(n), then uses those numbers to find all primes in the given range.
I'd like to know if:
- I'm using more memory than necessary
- I'm unnecessarily repeating some operations
- I can improve the style of this code
Note: I am not validating user input for simplicity sake.
import java.util.*;
public class PrimeLister {
private static ArrayList<Integer> segmentSieve(int upperBound) {
boolean[] primes = new boolean[upperBound + 1];
Arrays.fill(primes, true);
ArrayList<Integer> numbers = new ArrayList<>();
for (int i = 2; i <= upperBound; i++) {
if (!primes[i])
continue;
for (int j = i * i; j <= upperBound; j += i) {
primes[j] = false;
}
if (primes[i])
numbers.add(i);
}
return numbers;
}
private static int findOffset(int start, int prime) {
for (int i = 0; i < prime; i++)
if (start++ % prime == 0)
return i;
return -1;
}
public static void listPrimes(int lowerBound, int upperBound) {
ArrayList<Integer> segmentPrimes = segmentSieve((int) Math.floor(Math.sqrt(upperBound)));
int[] offsets = new int[segmentPrimes.size()];
boolean[] primes = new boolean[1 + upperBound - lowerBound];
Arrays.fill(primes, true);
for (int i = 0; i < offsets.length; i++) {
int tmp = segmentPrimes.get(i);
offsets[i] = findOffset(lowerBound, tmp);
for (int j = offsets[i]; j < primes.length; j += tmp) {
if (!primes[j] || (j + lowerBound) == tmp)
continue;
primes[j] = false;
}
}
for (int i = 0; i < primes.length; i++) {
if (primes[i] && (i + lowerBound) != 1)
System.out.println(i + lowerBound);
}
System.out.println();
}
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
int lowerBound = in.nextInt();
int upperBound = in.nextInt();
listPrimes(lowerBound, upperBound);
in.close();
}
}