Eratosthenes的筛子实施不检查某些数字

时间:2014-03-06 12:55:42

标签: java algorithm primes sieve-of-eratosthenes

我正在编写一个程序,使用良好的'Eratosthenes筛选算法(虽然有一个转折)来查找素数。为了将所需的字节数组的大小减半,我不代表任何偶数,并坚持使用奇数(通过整数除以2计算它们在数组中的位置)。

但是,我有一个问题。我的程序似乎并不认为17或113为素数,尽管它们确实是素数。这是我的代码:

public class Eratosthes {

    byte[] checklist;
    int range;

    public EratosthesConcurrent(int range) {
        this.range = range/2;
        this.checklist = new byte[this.range];
        this.initAllChecked();
        this.findPrimesSeq();
        this.printPrimes();
    }

    private void initAllChecked(){
        for(int i = 1; i < checklist.length; i++){
            checklist[i] = 1;
        }
    }

    private void crossOut(int i){
        checklist[i/2] = 0;
    }

    private void findPrimesSeq(){
        int curr = 3;
        outer: while(curr < range*2){
            for(int i = curr*curr; i < range*2; i+=2*curr){
                if(i != curr && i%curr == 0){
                    if(i == 113){
                        System.out.println(curr);
                    }
                    crossOut(i);
                }
            }

            secondLoop: for(int i = curr; i < range*2; i++){
                if(checklist[i/2] == 1 && curr != i){
                    curr = i;
                    break secondLoop;
                } else if(i == range*2-1 || i == range*2-2){ //Should be changed, might miss the last prime
                    break outer;
                }
            }
        }
    }

    public void printPrimes(){
        for(int i = 1; i < range; i++){
            if(checklist[i] == 1){
                System.out.println("Prime found: " + ((i*2)+1));
            }
        }
    }
}

将以下内容添加到crossOut方法不会产生任何输出:

if(i == 17 || i == 113){
    System.out.println("Found one of the numbers");
}

这对我来说很奇怪,因为该程序的打印输出排除了17和113,因此不会检查它们的任何倍数。这给我留下了一个字节数组,其中检查了所有素数......以及17或113的任何倍数。

如果有人能在我的程序中找到错误,我会很高兴 - 我自己一直在调试它几个小时,没有结果。提前谢谢。

2 个答案:

答案 0 :(得分:2)

问题似乎是你没有检查除以2。

您在某个时刻(特别是crossOut(16)的倍数)呼叫4,它会超出17的相应值。同样,112会导致113划掉。

变化:

if (i != curr && i % curr == 0) {

为:

if (i % 2 != 0 && i != curr && i % curr == 0) {

并且这两个都被打印为素数。

另外,我有点担心这个循环究竟在做什么 - 我没有太详细地看输出,虽然它实际上似乎是所有的素数,但我想你应该循环多次curr的{​​{1}},第一个是2*curr(不是curr*curr),是curr(不是2*curr)之间的增量,虽然我不是说你是什么这样做是不正确的,因为我需要更多的时间来准确理解你的代码是如何解决这个问题的。

答案 1 :(得分:0)

for(int i = curr*curr; i < range*2; i+=2*curr){

第一个值= 9然后转到15

curr = 3 - 3 * 3 = 9

i + = 2 * curr = 9 + 6

伪:

outerNum = sqrt[range]
array[boolean] size of range
array[0 & 1] = false

for i = 2 to outernum
       for j  = i to range
           if j % i != 0
               array[j] = false

for i = array[boolean] length
     print if array[i] = true

如果有任何错误,请记忆,请原谅。