Java项目Euler#10项目,正确数字



*免责声明,当我说"我已经验证这是正确的结果"时,请解释这一点,因为我已经根据Wolframalpha对答案进行了检查,我认为这很漂亮该死的准确。

*目标,找到所有质数的总和小于或等于2,000,000(200万)

*问题,每当我的测试值范围大约小于或等于

时,我的代码将输出正确的结果一旦测试输入大约大约1,300,000,

i不会输出正确的结果;我的输出将关闭...

测试输入:---- 199,999测试输出:--- 1,709,600,813正确的结果:1,709,600,813

测试输入:---- 799,999测试输出:--- 24,465,663,438正确的结果:24,465,663,438

测试输入:---- 1,249,999测试输出:--- 57,759,511,224正确的结果:57,759,511,224

测试输入:---- 1,499,999测试输出:--- 82,075,943,263正确的结果: 82,074,443,256

测试输入:---- 1,999,999测试输出:--- 142,915,828,925正确的结果: 142,913,828,925

测试输入:---- 49,999,999测试输出:--- 72,619,598,630,294正确的结果: 72,619,548,630,277

*我的代码,这是怎么回事,为什么它适用于较小的输入?我什至使用了很长的时间,而不是int ...

long n = 3;
long i = 2;
long prime = 0;
long sum = 0;
while (n <= 1999999) {
  while (i <= Math.sqrt(n)) {    // since a number can only be divisible by all
                            // numbers
                            // less than or equal to its square roots, we only
                            // check from i up through n's square root!
    if (n % i != 0) {       // saves computation time
      i += 2;               // if there's a remainder, increment i and check again
    } else {
      i = 3;                // i doesn't need to go back to 2, because n+=2 means we'll
                            // only ever be checking odd numbers
      n += 2;               // makes it so we only check odd numbers
    }
  }                         // if there's not a remainder before i = n (meaning all numbers from 0
                            // to n were relatively prime) then move on
  prime = n;                // set the current prime to what that number n was
  sum = sum + prime;
  i = 3;                    // re-initialize i to 3
  n += 2;                   // increment n by 2 so that we can check the next odd number
}
System.out.println(sum+2); // adding 2 because we skip it at beginning

帮助:)

问题是,您无法正确检查将最新的素数添加到总和是否小于限制。您有两个嵌套循环,但您只检查外循环的限制:

while (n <= 1999999) {

,但您不检查内部循环:

 while (i <= Math.sqrt(n)) {

然而,您反复前进到该循环中的下一个候选Prime(n += 2;)。这允许候选素数超过限制,因为仅检查了外循环的每次迭代中的第一个候选素数,而不是内部循环访问的任何后续候选素数中的第一个候选素数。

以1,999,999的限值为例,这使得在1,999,999之后,即2,000,003。您会注意到,正确的值为142,913,828,922,恰好比142,915,828,925的结果少2,000,003。

更简单的结构

这是可以使用标签的标签和continue来简化结构的一种方法:

public static final long primeSum(final long maximum) {
    if (maximum < 2L) return 0L;
    long sum = 2L;
    // Put a label here so that we can skip to the next outer loop iteration.
    outerloop:
    for (long possPrime = 3L; possPrime <= maximum; possPrime += 2L) {
        for (long possDivisor = 3L; possDivisor*possDivisor <= possPrime; possDivisor += 2L) {
            // If we find a divisor, continue with the next outer loop iteration.
            if (possPrime % possDivisor == 0L) continue outerloop;
        }
        // This possible prime passed all tests, so it's an actual prime.
        sum += possPrime;
    }
    return sum;
}

相关内容

  • 没有找到相关文章

最新更新