目前我有这个限制为n< 2 ^ 32-1。鉴于数组中元素的限制,我不完全确定如何进一步扩展限制。
Sieve:
public class Main {
public static void main(String args[]){
long N = 2000000000;
// initially assume all integers are prime
boolean[] isPrime = new boolean[N + 1];
for (int i = 2; i <= N; i++) {
isPrime[i] = true;
}
// mark non-primes <= N using Sieve of Eratosthenes
for (int i = 2; i*i <= N; i++) {
// if i is prime, then mark multiples of i as nonprime
// suffices to consider mutiples i, i+1, ..., N/i
if (isPrime[i]) {
for (int j = i; i*j <= N; j++) {
isPrime[i*j] = false;
}
}
}
}
}
我如何修改它以超过n = 2 ^ 32-1?
答案 0 :(得分:4)
您可以使用BitSet
个对象数组来表示长位集。这是完整的例子:
public class Main {
private static class LongBitSet {
// max value stored in single BitSet
private static final int BITSET_SIZE = 1 << 30;
BitSet[] bitsets;
public LongBitSet(long limit) {
bitsets = new BitSet[(int) (limit/BITSET_SIZE+1)];
// set all bits by default
for(int i=0; i<bitsets.length; i++) {
bitsets[i] = new BitSet();
int max = (int) (i == bitsets.length-1 ?
limit % BITSET_SIZE : BITSET_SIZE);
bitsets[i].set(0, max);
}
}
// clear specified bit
public void clear(long pos) {
bitsets[(int) (pos / BITSET_SIZE)].clear((int) (pos % BITSET_SIZE));
}
// get the value of the specified bit
public boolean get(long pos) {
return bitsets[(int) (pos / BITSET_SIZE)].get((int) (pos % BITSET_SIZE));
}
// get the number of set bits
public long cardinality() {
long cardinality = 0;
for(BitSet bs : bitsets) {
cardinality += bs.cardinality();
}
return cardinality;
}
}
public static void main(String args[]) {
long N = 4000000000L;
// initially assume all integers are prime
LongBitSet bs = new LongBitSet(N+1);
// clear 0 and 1: non-primes
bs.clear(0);
bs.clear(1);
// mark non-primes <= N using Sieve of Eratosthenes
for (long i = 2; i * i <= N; i++) {
if (bs.get(i)) {
for (long j = i; i * j <= N; j++) {
bs.clear(i * j);
}
}
}
System.out.println(bs.cardinality());
}
}
N = 4_000_000_000L
的这个程序需要大约512Mb的内存,工作几分钟并打印189961812
,这是正确的素数低于4亿according to Wolfram Alpha。如果你有足够的内存,你可以尝试设置更大的N.
答案 1 :(得分:2)
您可以对筛子进行分段:您可以分配许多小型数组,而不是分配单个巨大的数组。如果要查找高达10 ^ 10的素数,可以使用大小为10 ^ 6左右的数组(或更好,BitSet
s)。然后你运行筛子10 ^ 4次。每次你运行一个新的细分时,你需要找到从筛子开始每个素数的位置,但这并不是太难。
除了允许更小的内存使用外,这还可以在缓存中保留更多的内存,因此它通常要快得多。
答案 2 :(得分:1)
我看到了选项:
打包16个数字/ 1个字节
使用多个表格
您可以一次使用更多方法
备用内存可以组合16/32/64位变量