I'm trying to find the sum of primes below 2 million in Java [duplicate]

穿精又带淫゛_ 提交于 2019-12-13 09:17:28

问题


I'm trying to find the sum of primes below millions. My code works when I try to find the sum of primes below hundred thousands but when I go large numbers it doesn't work. So I need some help to get this work for big numbers...

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);
  }
}

回答1:


  1. Your code could be improved by making the inner loop stop earlier. If a number N is not prime, then it must have at least one factor (apart from 1) that is less or equal to sqrt(N). In this case, this simple change should make the program roughly 1000 times faster.

  2. For a simple and (more) efficient algorithm, read up on the Sieve of Eratosthenes.

  3. Bug - your sum needs to be a long. An int will probably overflow.

Note that the classic formulation of Sieve of Eratosthenes needs a large array of booleans (or a bitmap) whose size depends on the largest prime candidate you are interested in. In this case that means a 2Mbyte array (or smaller if you use a bitmap) ... which is too small to worry about. Also, you can reduce the memory usage by sieving in stages, though it makes the code more complicated.




回答2:


Rather than trying to divide by all the numbers below i you could potentially keep the found prime numbers in a list and try to divide by those prime numbers (since any non prime number will be divisible by a prime number less than that).

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;
}

This gave the answer in 8 seconds




回答3:


I suspect integer overflow in i, j, sum - try making them all longs. In the sample code you shouldn't be getting overflows as Java ints are meant to be 32 bit but at some stage you certainly will.

As already mentioned - i only needs to iterate to the square root of n. So I would replace this line:

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

With:

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

Note that calculating the square root outside the program loops will also speed things up a bit.

Also the sieve algorithm would be faster but requires Java to create an array containing n elements and at some stage that is going to fail with insufficient memory.




回答4:


The best algorithm for this program uses the Sieve of Eratosthenes:

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

Then sumPrimes(2000000) returns the sum of the primes less than two million, in about a second. I'll leave it to you to translate to Java, with an appropriate data type for the sum. If you're interested in programming with prime numbers, I modestly recommend this essay at my blog.



来源:https://stackoverflow.com/questions/18553891/im-trying-to-find-the-sum-of-primes-below-2-million-in-java

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!