Prime生成数字查找器不能产生正确的输出

时间:2012-01-08 18:00:03

标签: java debugging primes

我正在解决这个问题:

  

考虑30:1,2,3,5,6,10,15,30的除数   可以看出,对于每个除数d为30,d + 30 / d为素数。

     

求出所有正整数n的总和不超过100 000 000   这样,对于n的每个除数d,d + n / d是素数。

我确信我已经拥有它,但是唉,这显然给了我错误的答案(12094504411074)。

我很确定我对Eratosthenes的筛子正在工作(但可能没有),所以我认为问题出在算法的某个地方。它似乎得到n = 30的正确答案(1+2+6+10+22+30 = 71 - 这是正确的吗?),但随着数字变大,它显然停止工作。

这是我的Java代码:

import java.util.HashSet;
public class Generators {
static HashSet<Integer> hSet = new HashSet<Integer>();

public static void main(String[] args) {
    // TODO Auto-generated method stub
    int n = 100000000; 
    sieveErat(n + 1); //Fill a hashSet with prime numbers
    System.out.println("Sieve complete");
    int check = 0; 

    long sum = 3;


    for(int i = 2; i <= n; i++){
        int numDivisors = 0; 
        int numPrimeChecks = 0; 
        boolean done = false;
        if(!hSet.contains(i+1)){ //i+1 must be a prime number for i to be prime generating
            continue;
        }
        else{
            for(int j = 2; j < i/2; j++){
                if(i%j == 0){
                    numDivisors++;
                check = j + i/j;
                if(hSet.contains(check)){
                    done = true;
                    numPrimeChecks++;
                }
            }else{
                break;
            }           

    }
            if(numPrimeChecks == numDivisors && done){

                sum += i; 
            }
        }

    }
    System.out.println(sum);
}

public static void sieveErat(int N){
boolean[] isPrime = new boolean[N + 1];

    for (int i = 2; i <= N; i++) {
        isPrime[i] = true;
        //count++;
    }
    // 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;
            //    count--;
            }
        }

    }


    for(int i = 2; i < isPrime.length; i++){
        if(isPrime[i]){
            hSet.add(i);
        }
    }
   // System.out.println(count);



}
}

1 个答案:

答案 0 :(得分:1)

你筛子的数学对我来说很好看。我把它砍掉来使用BitSet,它更节省空间。 5761455素数低于100,000,000是否正确?

一旦我的代码正常工作,我得到了相同的数字(12094504411075应该得到什么?

我认为这有点不对(为了清晰起见,我更改了变量名称以匹配问题)

    for(int d = 2; d < Math.sqrt(n+3); d++) {
      if (n % d == 0) {
        numDivisors++;
        int check = d + n / d;
        if (primes.get(check)) {
          // **** What does done mean??? ****
          //done = true;
          numPrimeChecks++;
        } else {
          // **** Added! Got a divisor that did not check. No point in going on.
          break;
        }
      } else {
        // **** Why break here??? ****
        //break;
      }

    }

NB 我已编辑此代码以反映我们最终认定的正确解决方案。

为什么在您点击不d d的{​​{1}}时,您会突然离开n圈?肯定是不对的。

但是,当你有一个不检查的除数​​时,我认为你可以突破d循环。

此外,您done的预期功能是什么?它似乎没有实际功能。

而且,为什么要在sum开始3

删除break我现在获得值1739023853139。这是对的吗?

<强>加

这是我的筛子。与您的相同,但构建BitSet,在这种情况下,结构比HashSet更有效:

public static BitSet sieveOfEratosthenes(int n) {
  BitSet isPrime = new BitSet(n);

  // Iniially all numbers are prime.
  for (int i = 2; i <= n; i++) {
    isPrime.set(i);
  }

  // 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.get(i)) {
      for (int j = i; i * j <= n; j++) {
          isPrime.clear(i * j);
      }
    }

  }

  //System.out.println("Found " + isPrime.cardinality() + " primes");
  return isPrime;
}