我试图在Java中找到低于200万的素数之和

时间:2013-08-31 23:52:00

标签: java primes

我试图找到数百万以下的素数之和。当我试图找到低于数十万的质数总和时,我的代码有效,但是当我输入大数字时它不起作用。所以我需要一些帮助才能让大数据工作......

import java.util.Scanner;
public class sumPrime {

  public static void main (String args []){

    long n = 2000000; int i; int j;int sum =0;
    for (i=2; i <n; i++){
        for (j=2; j<i; j++){
            if (i%j==0){
                break;
            }
        }
        if (i==j){
            sum +=i;
        }
    }
    System.out.print(sum);
  }
}

4 个答案:

答案 0 :(得分:4)

  1. 可以通过提前停止内部循环来改进代码。如果数字N不是素数,那么它必须至少有一个因子(除了1)小于或等于sqrt(N)。在这种情况下,这个简单的改变应该使程序快大约1000倍。

  2. 对于简单且(更有效)的算法,请阅读Sieve of Eratosthenes

  3. 错误 - 您的sum必须是longint可能会溢出。

  4. 请注意,Eratosthenes筛选器的经典配方需要大量的布尔值(或位图),其大小取决于您感兴趣的最大素数候选者。在这种情况下,这意味着一个2Mbyte数组(如果使用则更小)一个位图)...太小而不用担心。此外,您可以通过分阶段筛选来减少内存使用量,但这会使代码更复杂。

答案 1 :(得分:2)

不是试图除以i以下的所有数字,而是可以将找到的素数保留在列表中并尝试除以那些素数(因为任何非素数都可以被低于该素数的素数整除)

public static long sumPrime2() {
    List<Long> primes = new ArrayList<>();
    primes.add(2L);
    primes.add(3L);
    long primeSum = 5;

    for (long primeCandidate = 5; primeCandidate < 2000000; primeCandidate = primeCandidate + 2) {
        boolean isCandidatePrime = true;
        double sqrt = Math.sqrt(primeCandidate);
        for (int i = 0; i < primes.size(); i++) {
            Long prime = primes.get(i);
            if (primeCandidate % prime == 0) {
                isCandidatePrime = false;
                break;
            }
            if (prime > sqrt) {
                break;
            }
        }
        if (isCandidatePrime) {
            primes.add(primeCandidate);
            primeSum += primeCandidate;
        }
        System.out.println(primeCandidate);
    }
    System.out.println(primes.size());
    return primeSum;
}

这给出了8秒的答案

答案 2 :(得分:1)

我怀疑i,j,sum中的整数溢出 - 尝试将它们全部填满。在示例代码中,您不应该溢出,因为Java int是32位,但在某些阶段你肯定会。

如前所述 - 我只需要迭代到n的平方根。所以我会替换这一行:

for (i=2; i <n; i++){

使用:

long limit=sqrt(n);
for (i=2; i <limit; i++){

请注意,计算程序循环外的平方根也会加快速度。

筛选算法也会更快但需要Java来创建一个包含n个元素的数组,并且在某个阶段会因内存不足而失败。

答案 3 :(得分:0)

此程序的最佳算法使用了Eratosthenes的Sieve:

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

然后sumPrimes(2000000)在大约一秒钟内返回少于两百万的素数之和。我会留给你翻译成Java,并提供适当的数据类型。如果您对使用素数进行编程感兴趣,我会在我的博客上谦虚地推荐这个essay