【问题标题】:Optimize calculation of prime numbers [duplicate]优化素数的计算[重复]
【发布时间】:2013-03-17 00:04:23
【问题描述】:

我正在尝试来自 Project Euler 的 Problem 3,但我的算法太慢了。有谁知道如何优化这个?我要计算的数字是 600851475143L。计算这个需要很长时间,所以我需要一种方法来加快计算速度。

逻辑:

  • 遍历从 3 到该数字 1 的所有数字
  • 对于这些数字中的每一个,通过将它们除以它们之间的所有数字来检查它们是否为素数,如果它们不除以它们中的任何一个,则它们是素数。
  • 如果是素数,则将它们添加到数组中。

    public static void problem3(long number){
    
    long number2 = number;
    long sqrtNumber = (long)Math.sqrt(number2);
    
    
    int indexNum = 1;
    boolean isPrime = false;
    
    int primeNums[] = new int[2];
    primeNums[0] = 2;
    
    //puts prime numbers into an array
    for(int y = 3; y < sqrtNumber; y++){
       isPrime=true;
       for(int theNum = 2; theNum < y; theNum++){
           //if y divides evenly by any number then it is not prime         
           if(y%theNum==0){
               //dont store in array
               isPrime=false;
               break;
           }
       }
    
       if(isPrime == true){
           //add to array
           System.out.println(y);
           //put y in the array and exapnd the array
           //System.out.println("y: " + y);
           primeNums[indexNum] = y;
    
           int[] newArray = new int[primeNums.length + 1];
           System.arraycopy(primeNums, 0, newArray, 0, primeNums.length);
    
           primeNums = newArray;
    
           indexNum++;
       }
    }
    

********** 更新 **************

我计算到平方根,这大大加快了计算速度,但我还做了其他事情,即在我发现数字不是素数时在 forloop 中添加一个 break 语句来中断。我编辑了上面的代码以反映这些变化。

虽然我的算法在计算质因数方面仍然是错误的,所以我需要看看它,也许会提出一个新问题。


【问题讨论】:

  • 您应该实现Sieve of Eratosthenes 以解决问题。
  • 通过试除法进行简单的因式分解最多需要几毫秒(此处小于 100 微秒)。
  • 请去掉所有令人困惑的**edit** 注释。没有人关心您遇到的错误,并且版本控制可供任何人检查。您的代码目前不可读。
  • Project Euler 的问题 3 不会要求您提供低于 600851475143 的所有素数,也不会要求您提供低于 600851475143 的最大素数。它会要求您提供 600851475143 的最大素数,即这样的数字 d 600851475143 % d == 0Google Search for problem 3 on StackOverflow shows 7460 hits.

标签: java performance algorithm primes


【解决方案1】:

您不必除以每个数字。您只需将每个素数除以 2 和您的数字的平方根。

【讨论】:

  • 我想我在其他地方看到过。但是为什么只将每个素数除以平方根
  • 因为对于每一个能被 x 整除的素数 p,x 都能被 x/p 整除。如果 p > sqrt(x),则 x/p
  • 好吧,你只需要去平方根,因为如果某个小于平方根的数字除以你的数字,那么这两个的商必须大于平方根。例如,取数字 36。18 除以 36,但您不必测试 18,因为您已经测试了 2。您需要测试的最高数字是 6。至于为什么只是素数?如果 4 整​​除一个数,则 2 必须整除它。因此,如果您已经消除了 2,那么您已经消除了 4 作为一个因素。
  • 对不起,这完全超出了我的想象,但我相信你的话并做出改变。 :)
  • 让我再举一个例子。假设你想知道 67 是否是素数。 63 的平方根略高于 8。所以你测试 2。不。测试 3。不。跳过4,为什么?因为如果它不能被 2 整除,它就不能被 4 整除。测试 5 - 不。跳过6,同样的原因。测试 7 - 不。测试 8 - 不。现在我们可以停下来了。它不能被 9 整除,因为 9*8 大于 67,并且我们已经消除了 67 等于 9*2、9*3、9*4、9*5、9*6 和9*7,因为我们测试(或跳过)了所有这些数字。
【解决方案2】:

您可以做的第一件事是只通过您正在测试的数字的平方根来测试可能的因素,因为如果您发现一个大于平方根的因素,那么您应该找到一个小于平方根。

如果您需要更多性能,请使用Sieve of Eratosthenes。这允许您使用先前素数的结果来减少确定较大数字是否为素数的工作。

【讨论】:

  • 我想我在其他地方看到过。但是为什么只将每个素数除以平方根
  • 考虑253,即11 * 23。平方根约为15.9。如果您找到 23(大于平方根),那么您应该已经找到 11(小于平方根)。如果你找不到小于或等于平方根的因子,那么你也不会找到大于平方根的因子。
  • @PhilHunter 因为您只想要素数,所以较大的非素数将是数字的平方根。作为示例,sqrt(100) = 10.
  • 这里不需要 Eratosthenes 的筛子,因为不需要测试任何数字的素数。适当的试除因式分解(例如这里的 stackoverflow.com/a/12046123/849891 )产生的因子是构造上的素数。
猜你喜欢
  • 1970-01-01
  • 2018-03-29
  • 2016-08-05
  • 2019-04-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-06-28
  • 2015-08-19
相关资源
最近更新 更多