简体   繁体   English

欧拉项目3:最大的主要因素

[英]Project Euler Number 3: Largest prime factor

Here is my code: 这是我的代码:

public class LargestPrimeFactor {

/**
 * @param args the command line arguments
 */
public static boolean isPrime(long x){
    for (int y=2; y<x; y++){
        if (x%y==0){
            return false;
        }
    }
    return true;
}

public static void main(String[] args) {
    System.out.println("Find out the largest prime factor of 600851475143");
    long num=600851475143L;
    int largest=0;
    int y=0;
    for (int x=2; x<num; x++){
        if (num%x==0&&isPrime(x)==true){
            System.out.println(x);
        }
    }
    System.out.println(largest);
}

Here is the output: 这是输出:

Find out the largest prime factor of 600851475143
71
839
1471
6857
-716151937
-408464633
-87625999
-10086647
-5753023
-1234169
-486847
-104441
-59569
-6857
-1471
-839
-71
-1
Exception in thread "main" java.lang.ArithmeticException: / by zero
    at largestprimefactor.LargestPrimeFactor.main(LargestPrimeFactor.java:32)
Java Result: 1
BUILD SUCCESSFUL (total time: 2 minutes 10 seconds)

How do I print out the largest number? 如何打印出最大的数字? and why does the output show negative numbers when "x" is supposed to be constantly increasing, never decreasing? 当“ x”应该不断增加而不是减少时,为什么输出显示负数?

UPDATE 更新

Here is my edited code: 这是我编辑的代码:

public static boolean isPrime(long x){
    for (int y=2; y<x; y++){
        if (x%y==0){
            return false;
        }
    }
    return true;
}

public static void main(String[] args) {
    System.out.println("Find out the largest prime factor of 600851475143");
    long num=600851475143L;
    long largest=0;
    int y=0;
    for (long x=2; x<num/2; x++){
        if (num%x==0&&isPrime(x)==true){
            System.out.println(x);
            if (largest<x){
                largest=x;
            }
        }
    }
    System.out.println(largest);
}

Here is the new output 这是新的输出

Find out the largest prime factor of 600851475143
71
839
1471
6857
0
BUILD SUCCESSFUL (total time: 318 minutes 31 seconds)

How do I get the final answer to be printed out as "6857" rather than "0"? 如何获得最终答案以“ 6857”而不是“ 0”的形式打印出来? Also, if you notice, the run time for the program was a little over 5 hours. 另外,如果您注意到,该程序的运行时间将超过5个小时。 How do I speed up this process? 如何加快此过程?

You are using an int for the for loop, which is overflowing. 您正在for循环中使用int ,该循环正在溢出。 Use a long variable to iterate. 使用长变量进行迭代。

for (int x=2; x<num; x++){
     ^^^

The reason for the negative values is that it is wrapping around. 负值的原因是它回绕。 If you want to find just the largest, you could use a new long variable to store the max-seen so far. 如果您只想找到最大的,则可以使用新的long变量来存储到目前为止的最大可见数。 Another way is to simply iterate over the range in reverse . 另一种方法是简单地反向迭代范围。

Additionally, you can shorten your loop to just check till the square root of the given number. 此外,您可以缩短循环,仅检查直到给定数字的平方根即可。 If you find a factor, you can do (num / ans) to find the larger factor. 如果找到一个因数,则可以执行(num / ans)查找较大的因数。

You can speed up the process significantly with a few tricks: 您可以通过以下一些技巧大大加快该过程:

  1. There's no use checking any even numbers other than two. 检查两个以外的偶数没有用。 Use only two and odd numbers as potential factors. 仅使用两个和奇数作为潜在因子。
  2. When you find a prime factor, divide the input number by that. 找到素数时,将输入数除以该数。 This makes it much smaller as you go along, cutting the time significantly. 这样一来,它的体积就会大大减小,从而大大节省了时间。
  3. Stopping when the potential factor is greater than the square root of the input number is much, much quicker than stopping when the potential factor is greater than half of the number. 当潜在因子大于输入数的平方根时停止比在潜在因子大于输入数的平方根时停止快得多。 Also, don't calculate the square root inside the condition. 另外,不要计算条件内部的平方根。 Save it in a variable and recalculate it only when the input number has been changed by being divided by one of its prime factors. 将其保存在变量中,然后仅当输入数字除以其主要因子之一而已更改时,才重新计算它。
  4. Don't bother checking whether odd potential factors are prime. 不要费心检查奇数潜在因素是否为素数。 If they're not prime, their own prime factors will have been divided out of the number already, so the potential factor will quickly fail the (x % factor == 0L) check, which is a much, much faster check than isPrime(factor) . 如果它们不是素数,则它们自己的素因数将已经从数量中除掉,因此潜在因数将很快无法通过(x % factor == 0L)检查,这比isPrime(factor)

The following code combines these ideas and finds the answer in about a tenth of a second: 以下代码结合了这些想法,并在大约十分之一秒的时间内找到了答案:

public final class Euler3 {
    // Modified from https://optimi.wordpress.com/2010/12/02/how-to-compute-64-bit-integer-square-roots-very-quickly/
    public static final long floorSqrt(final long x) {
        if (x < 0L) throw new IllegalArgumentException("Cannot take the square root of a negative number");
        if ((x & 0xfff0000000000000L) == 0L) return (long) StrictMath.sqrt(x);
        final long result = (long) StrictMath.sqrt(2.0d*(x >>> 1));
        return result*result - x > 0L ? result - 1L : result;
    }

    public static final long biggestPrimeFactor(long x) {
        // Properly handle zero.
        if (x == 0L) return 0L;

        // Properly handle negative numbers.
        if (x < 0L) x = -x;

        long lastPrimeRemoved = 1L;
        long sqrtX = floorSqrt(x);

        // Handle the prime factor 2.
        // (x & 1L) == 0L is true whenever the number is even.
        // x >>>= 1 replaces x with x divided by 2 if x is positive.
        // >>>= is used because the minimum long can't be negated above.
        if ((x & 1L) == 0L) {
            x >>>= 1; 
            while ((x & 1L) == 0L) x >>>= 1;

            lastPrimeRemoved = 2L;
            sqrtX = floorSqrt(x);
        }

        // Handle the odd prime factors.
        for (long factor = 3L; (x != 1L) && (sqrtX >= factor); factor += 2L) {
            if (x % factor == 0L) {
                x /= factor;
                while (x % factor == 0L) x /= factor;

                lastPrimeRemoved = factor;
                sqrtX = floorSqrt(x);
            }
        }

        // If we removed all the prime factors, return the last one we removed.
        if (x == 1L) return lastPrimeRemoved;
        // Otherwise, whatever remains is itself a large prime. Return that.
        else return x;
    }

    public static final void main(final String[] args) {
        System.out.println(biggestPrimeFactor(600851475143L));
    }
}

A possible solution is to use recursion as shown below: 一种可能的解决方案是使用如下所示的递归:

public class PrimeFactor{

    public static void main(String[] args){
        long n = 600851475143L;     
        System.out.println("LARGEST = "+largestPrime(2,n)); 
    }

    public static long largestPrime(long f, long  val){
        if (val == f){
            return f;
        }
        else if (val % f ==0) 
        {   
            return largestPrime(f, val/f);  
        }
        else
        { 
            return largestPrime(f+1, val);
        }
    }

}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM