我试图找到数百万以下的素数之和。当我试图找到低于数十万的质数总和时,我的代码有效,但是当我输入大数字时它不起作用。所以我需要一些帮助才能让大数据工作......
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);
}
}
答案 0 :(得分:4)
可以通过提前停止内部循环来改进代码。如果数字N
不是素数,那么它必须至少有一个因子(除了1)小于或等于sqrt(N)
。在这种情况下,这个简单的改变应该使程序快大约1000倍。
对于简单且(更有效)的算法,请阅读Sieve of Eratosthenes。
错误 - 您的sum
必须是long
。 int
可能会溢出。
请注意,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。