Sieve Eratosthenes大于int

时间:2015-09-04 04:44:08

标签: java algorithm

我想找到100亿以下的所有素数。这是int可以容纳的5倍(这是数组的限制,无论类型如何)。尝试一次分配超过12亿,导致堆空间错误。我尝试使用List而不是布尔数组,但arrayLists的set element方法只能索引到int。让我烦恼的是,很快进入筛子的是不到一个整数个元素没有被划掉。应该工作的一种方法是创建一个包含10个数组的分区并将它们粉碎在一起......但这样做会很难看。如果您有任何优雅的解决方法,请告诉我。 (除了使用Python lol)。我已经有一个n ^ 2/2暴力实施,但这需要很长时间才能运行,所以我真的希望尽快解决这个问题。我的Sieve实现工作量高达1.2亿,如下所示:

public class SieveEratosthenes {
private boolean[] nums;
public static void main(String[] args) {
    int n = 1000000;
    SieveEratosthenes s = new SieveEratosthenes(n);
    for(int i=0;i<s.nums.length;i++){
        if(s.nums[i]){
            System.out.println(i);
        }
    }
}

public SieveEratosthenes(int max){
    sieve(max);
}

private boolean[] sieve(int max){
    nums = new boolean[max+1];
    initFlags();
    for(int i=2;i*i<max;i++){
        for(int j=i*i;j<=max;j+=i){//cross off non-primes
            nums[j]=false;
        }
    }
    return nums;
}
private void initFlags(){
    if(nums != null&&nums.length>1){
        nums[0]=false;
        nums[1]=false;
        nums[2]=true;
    }
    for(int i=3;i<nums.length;i++){
        nums[i]=true;
    }
}

public List<Long> sieveToList(){
    List<Long> sieveList = new ArrayList();
    for(int i=0;i<nums.length;i++){
        if(nums[i]){
            sieveList.add((long)i);
        }
    }
    return sieveList;
}

3 个答案:

答案 0 :(得分:2)

您可以使用以下方法:

  • 使用10 ^ 7英寸的筛子或适合您的任何尺寸。
  • 然后,对于每个筛子的实现,最后,将所有计算的素数保存在您熟悉的任何数据结构中(ArrayList会这样做)。
  • 现在,这样做1000次,使用循环(当然),每次,你的筛子将在接下来的10 ^ 7范围内计算质数。因此,在第一次迭代时,将计算0-10 ^ 7的所有素数。然后,从10 ^ 7 + 1到2 * 10 ^ 7等。

PS:如果你想要代码,我会为你做,但我建议你尝试一次。我可能错了,但我认为这种方法就是他们所谓的 $email= mysqli_real_escape_string($db_con,$_POST['email']); $psw= mysqli_real_escape_string($db_con,$_POST['psw']); $query = "INSERT INTO `users` (`email`,`psw`) VALUES ('".$email."','".$psw."')";

答案 1 :(得分:0)

你应该放弃使用数组。正如你所说,它们不适合非常大的套装。算法的一个合理的近似是“交叉”,因为你通过测试它检查每个素数它是任何先前素数的倍数。我没有分析过这个的表现。

class Sieve {
    private long current = 2;
    private final List<Long> primes = new ArrayList<>();

    public long nextPrime() {
        while (primes.stream().anyMatch(p -> current % p == 0))
            current++;
        primes.add(current);
        return current;
    }
}

答案 2 :(得分:0)

如果内存不是问题,请继续使用数组,因为它要快得多。如果内存成为问题,我建议调查BitSets。

虽然Java数据结构受限(据我所知)最大int大小约为20亿,但您可以创建自己的数据结构。一个非常简单的解决方案是创建一个类,在给定max int length的情况下将所请求的大小拆分为多个数组或位集,然后自动访问由您输入的长索引输入给出的类。我希望这是有道理的。如果您有任何问题,请告诉我们!