Eratosthenes筛选 - 实现返回一些非素数值?

时间:2014-08-22 04:44:38

标签: java math primes sieve

我使用伪代码实现了Java中的Eratosthenes Sieve:

public static void sieveofEratosthenes(int n) {
    boolean numArray[];

    numArray = new boolean[n];
    for(int i = 0; i < n; i++)
        numArray[i] = true;

    int a = 0;

    for(int i = 2; i < Math.sqrt((double)n); i++) {
        if(numArray[i])  {
            for(int j = (int)Math.pow(i, 2); j < n; a++) {
                numArray[j] = false;
                j += (a * i);
            }
        }
    }

    for(int i = 2; i < n; i++) {
        if(numArray[i])
            System.out.println(i);
    }
}

当我15岁时,它给我的输出:

2
3
5
7
8
11
12
13
14

为什么其中一些值不正确?我相信我的错误在于如何定义和使用bool数组。谢谢!

4 个答案:

答案 0 :(得分:4)

        for(int j = (int)Math.pow(i, 2); j < n; a++) {
            numArray[j] = false;
            j += (a * i);
        }

应该阅读

        for(int j = (int)Math.pow(i, 2); j < n; j+=i) {
            numArray[j] = false;
        }

答案 1 :(得分:2)

SoE的工作原理是它接受每个数字并“删除”其后面可被其整除的所有数字。所以基本上每个数字 x + k * x 其中 k&gt; 0 即可。这可以通过简单地将 x 添加到初始 x ^ 2 ,然后迭代地添加 x 来完成。这里:

for(int j = (int)Math.pow(i, 2); j < n; a++) {
    numArray[j] = false;
    j += (a * i);
}

您没有添加 x ,而是 a * x ,因此当 a 递增时,您会跳过一些数字(因此您将删除4,6,10,16等,看到模式?它将初始值加上2,4,6等)所以你应该坚持:

for(int j = (int)Math.pow(i, 2); j < n; j+=i) {
    numArray[j] = false;
}

答案 2 :(得分:0)

问题在于

 j += (a * i);

在循环中,这个陈述逐渐将j乘以a * i和 add 它与j.So替换上面的行,

 j = (a * i);

它会起作用。 是的,初始化

a=2

因为我们不希望numarray [0]或numarray [1]初始化或使用。 如果有任何查询请做评论。感谢

答案 3 :(得分:0)

这并没有直接解决你的问题,但由于它已经得到了解答,我认为重复它没有任何意义。不过,看一下你的代码,我建议使用整数乘法而不是Math.powMath.sqrt来获得更好的性能,例如:

for(int i = 2; i*i < n; i++) {
    if(numArray[i])  {
        for(int j = i*i; j < n; j += i) {
            numArray[j] = false;
        }
    }
}

不可否认,这些调用只会在外循环的每次迭代中进行一次,因此改进可能不会非常显着。但是,调用Math.powMath.sqrt可能比单个整数乘法更加计算密集。此外,如果Java执行足够复杂的优化,i*i可能只计算一次并在两个地方使用,从而节省更多的计算周期。在这种情况下也没有整数超限的风险,因为i*i的上限是整数n