【问题标题】:Java Program to find sum of all prime numbers below 2,000,000 (Project Euler)Java 程序查找所有低于 2,000,000 的素数之和(Project Euler)
【发布时间】:2012-06-07 21:35:30
【问题描述】:

我正在尝试解决 Project Euler 的第 10th 个问题,但由于某种原因我无法正确解决。我在编程和 Java 方面真的很陌生,所以我不明白为什么它不起作用。问题的重点是求所有小于 2,000,000 的素数之和。

/*  The sum of the primes below 10 is 2 + 3 + 5 + 7 = 17.

    Find the sum of all the primes below two million.
*/  

public static void main(String[] args){

    long n = 1;
    long sum = 0;
    long limit;

    System.out.println("Enter the limit of n: ");
    limit = TextIO.getlnLong(); //TextIO is another input method
    while (limit <= 0){
        System.out.println("Enter the limit of n (must be positive): ");
        limit = TextIO.getlnLong();

    }       

    while (n < limit){ 
        n++;
        if (n % 2 != 0 && n % 3 != 0 && n % 5 != 0 && n % 7 != 0 && n != 1 || n == 2 || n == 3 || n == 5 || n == 7){ //this is my prime checking method, might be flawed

            sum = sum + n;  
            System.out.println(+sum);
        } //end if

    }//end while

    System.out.println("The sum of the primes below 2,000,000 is: " +sum);

} //end of main

【问题讨论】:

  • 你的素数检查方法肯定有缺陷。
  • 我还建议将素数检出分解为单独的方法。
  • 这是一个经过验证的Sieve,您可以使用。
  • 121 = 11*11。那不是素数……完美的正方形,是的。
  • 每当您在 SO 上发帖时,请非常清楚地说明您的问题。尽管人们可以编译和运行代码并看到您发布的问题,但最好清楚地指出您的程序是否没有编译或者您得到了一些不正确的答案。尽管在您的情况下,许多人指出的有缺陷的逻辑很容易被抓住。

标签: java


【解决方案1】:

如需高效质数检查方法,请阅读Sieve of Eratosthenes

【讨论】:

  • 对于高达 200 万的数字,他当然不需要过于高效的东西。我希望天真的实现需要几秒钟。
  • @CodeInChaos:也许吧,但暴力破解的东西通常不符合投射者的精神,他肯定需要一些有效的东西来解决以后与素数相关的问题。
  • 筛子需要某种集合、列表或向量来处理发现的不断增加的素数集合。目前,对于 zsherman 来说,嵌套的 for 循环和动态大小的数据结构太大了
  • @JustinDanielson 筛子本身指示每个数字是否为素数,无需将数字存储在筛子之外。
  • 我实际上也用埃拉托色尼筛解决了这个问题。对于以后的问题,它非常有用。 (它只需 0.05 秒即可运行)。
【解决方案2】:

你的主要方法坏了。如果一个数在 2 和该数的平方根之间没有任何除数,则该数是素数。 13*13 将通过您的素数检查功能。

for i to sqrt(n):
   if(n % i == 0):
       OH NO NOT PRIME DO SOMETHING HERE?
if something is prime
   add some stuff

【讨论】:

    【解决方案3】:

    这里有 2 个比普通解决方案更好的解决方案:

    1)遍历奇数(唯一的偶素数已经在总和中)并检查它们是否为素数:

    private static boolean isOddPrime(int x) {
        for ( int i = 3 ; i*i <= x ; i+=2 ){ 
            if ( x % i == 0 ) {
                return false;
            }
        }
        return true;
    }
    
    private static void sumOfPrimes1(int n) {       
        long sum = 2;
        for ( int i = 3 ; i < n ; i+=2 ) {
            if ( isOddPrime(i) ) {
                sum+=i;
            }
        }
        System.out.println(sum); 
    }
    

    2)使用埃拉托色尼筛法

    private static void sumOfPrimes2(int n) {
        boolean notPrimes[] = new boolean[n];   // default = false
        for ( int i = 2 ; i*i < n ; i++ ) {
            if ( !notPrimes[i] ) {
                for ( int j = i*i ; j < n ; j+=i ){
                    notPrimes[j] = true;
                }
            }
        }
        long sum = 2 ;
        for ( int i = 3 ; i < n ; i+=2 ) {
            if ( !notPrimes[i] ) {
                sum+=i;
            }
        }
        System.out.println(sum);
    }
    

    我使用“notPrimes”(复合)而不是“primes”作为数组,只是为了利用 Java 中的默认布尔值是false这一事实。

    性能

    n           |    2000000        8000000       16000000
    ------------+-------------------------------------------
    Solution 1  |    1309 ms        8574 ms       22757 ms
    Solution 2  |    119 ms         696 ms        1624 ms
    

    【讨论】:

      【解决方案4】:

      http://www.counton.org/explorer/primes/checking-if-a-number-is-prime/

      检查数字 N 是否为素数的一个捷径是我们不必依次尝试从 2 到 N (2, 3, 4, 5, 6 .....N-1) 中的每个数字来查看任何一个它们正好除以 N。

      exp :由于 3 是 18 的因数且 18/3=6,因此 18=3x6。我们只需要测试较小的数字 3,看看它是不是 18 的因数,而不是 6。同样,5 是 20 的因数,20=5x4,所以我们只需要测试较小的数字 4 作为因数。但是如果我们不知道一个数的因数怎么办?因此,测试一个数字是否为素数意味着我们只需要测试“较小”的因素。但是较小的因素在哪里停止而较大的因素从哪里开始呢?这里的原则是: 假设一个数是 N 的因数,并且它小于数 N 的平方根。那么第二个因数必须大于平方根。 我们可以通过上面的例子看到这一点:对于 18,我们只需要测试直到 18 的平方根即 4.243 的数字,即最多 4!这比测试 17 以内的所有数字要快得多!! 对于 25,我们需要测试直到并包括 25 的平方根(即 5)的数字。 而对于 37,我们只需要增加到 6(因为 6x6=36,所以 37 的平方根只会稍微大一点)。

      public static void main(String[] args) {
          long sum = 0;
          for (int i = 2; i < 2000000; i++) {
              if (isPrime(i)) {
                  sum += i;
              }
          }
          System.out.println(sum);
      }
      
      // check if a number is prime
      private static boolean isPrime(int number) {
          int sqrt = (int) Math.sqrt(number);
          boolean isPrime = true;
      
         // test up to square root of the number
         for (int i = 2; i <= sqrt; i++) {
              if (number % i == 0) {
                  isPrime = false;
                  break;
              }
          }
          return isPrime;
      }
      

      【讨论】:

        【解决方案5】:
        public static void main(String args[])
        {
          long n = 1;
          long sum = 0;
          long limit=Integer.parseInt(args[0]);
        
          while (n < limit)
          {
            n++;
            if(n % 2 != 0 && n % 3 != 0 && n % 5 != 0 && n % 7 != 0 && n != 1 || n == 2 || n == 3 || n == 5 || n == 7)
            {
              sum = sum + n;
            }
          }
        
        
            System.out.println("The sum of the prime numbers = " +sum);
         }
        

        【讨论】:

        • 您能否添加一些文字来描述这如何回答问题?
        • 同上。解释总是受到赞赏。否则,你会让每个人都承担起发现差异的任务
        • 这里 n 是起始数字,limit 是范围,可以是 2000000。while 循环用于检查数字达到限制。现在在循环内部,每个数字将在给定的 if 条件的帮助下检查是否为素数。如果它是一个素数,它将被添加到总和中。最后,所有素数都将被添加到 sum 并打印 sum。
        • @Sheena,是的,我同意它的同上!但我做了一些我认为其他人容易理解的更改。
        • 它将如何实际计算 200 万以下的素数,没有帮助,也没有以任何方式工作,怎么回事
        猜你喜欢
        • 2015-12-09
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-07-01
        • 2019-09-29
        相关资源
        最近更新 更多