使用Eratosthenes筛子的素数之和;答案太小了

时间:2013-06-11 19:37:25

标签: java primes sieve-of-eratosthenes

对于Project Euler problem #10,我写了一个程序来查找2到2,000,000之间所有素数的总和。

我的代码适用于较小的值,如50或100,但当我尝试使用2,000,000时,它会返回一个太小的值141,675。

我认为这可能是因为答案太长而无法长时间使用,这就是我使用BigInteger的原因,但我已经知道这不是一个因素。我很感激任何想法。

public class ProblemTen {


/**
 * Precondition:  all the bits in the set are set to true
 * This method uses the Sieve of Eratosthenes
 * @param p the starting prime number
 * @param b the BitSet array
 * @param s the length of the original BitSet array
 * @return BitSet with all the prime indexes set to true
 */
public static BitSet findPrimes(int p, BitSet b, int s) {
    //System.out.println(b);
    while (p*p < s) {  // repeat until p^2 > size of the ORIGINAL set 
        for (int i = 0; i <= b.length(); i++) {
            if (i%p == 0) { // if it's a multiple of p
                b.set(i, false); // set it to false (not prime)
            }
        }
        p = b.nextSetBit(p); // Make p = first bit that is set to true starting after the previous p index.
    }
    return b;
}

/**
 * @param args
 */
public static void main(String[] args) {

    int set = 2000000;

    BitSet bits = new BitSet(set);
    for (int i = 0; i < set; i++) {
        bits.set(i); // set all bits to True; when you print only the true ones print out
    }
    BitSet primeBits = new BitSet(set);
    primeBits = findPrimes(2, bits, set);
    //System.out.println("List of primes: " + primeBits);

    BigInteger sum = BigInteger.ZERO;
    for (int j = 0; j <= primeBits.length(); j++) {
        if (primeBits.get(j) == true ) {
            sum = sum.add(BigInteger.valueOf(j));
        }
    }

    System.out.println("Sum is: " + sum); // I get 142,913,687,247 which is 141,675 too small (142913828922)
}

}

3 个答案:

答案 0 :(得分:2)

    while (p*p < s) {  // repeat until p^2 > size of the ORIGINAL set 
        for (int i = 0; i <= b.length(); i++) {
            if (i%p == 0) { // if it's a multiple of p
                b.set(i, false); // set it to false (not prime)
            }
        }
        p = b.nextSetBit(p);
        // Make p = first bit that is set to true starting after the previous p index.
    }

将素数p所有倍数标记为复合,包括p本身。所以只有大于极限平方根的素数才能保持无标记。

  
      
  • 此方法使用Sieve of Eratosthenes
  •   

不,它没有。它使用试验部门。您将每个数字除以小于限制的平方根的所有素数,并检查余数是否为0。

循环应该是

for(int i = p*p; i < b.length; i += p)
    b.set(i,false);

实施Eratosthenes筛选。

答案 1 :(得分:0)

for (int i = 0; i <= b.length(); i++)

将其更改为

for (int i = p+1; i <= b.length(); i++)

否则,您将删除小于2,000,000 ^ .5

的所有素数

答案 2 :(得分:0)

你的解决方案不是 Eratosthenes的Sieve,它是试验部门;模运算符将它放弃。这是一个适当的Eratosthenes筛子的伪代码,它总结了它找到的素数:

function sumPrimes(n)
    sum := 0
    sieve := makeArray(2..n, True)
    for p from 2 to n step 1
        if sieve[p]
            sum := sum + p
            for i from p * p to n step p
                sieve[i] := False
    return sum

我会留给你将代码翻译成Java。如果您对素数编程感兴趣,我谦虚地在我的博客上推荐这个essay,其中包括Java中的Eratosthenes筛选。那里的代码也可以帮助你解决其他一些Project Euler问题。