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

时间:2015-12-31 03:20:38

标签: java

这是我的代码:

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);
}

这是输出:

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)

如何打印出最大的数字?为什么当&#34; x&#34;时输出显示负数。应该是不断增加,永不减少?

更新

这是我编辑的代码:

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);
}

这是新输出

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

如何将最终答案打印出来&#34; 6857&#34;而不是&#34; 0&#34;?此外,如果您注意到,该程序的运行时间有点超过5小时。我如何加快这个过程?

3 个答案:

答案 0 :(得分:1)

您正在使用int for循环,它正在溢出。 使用long变量进行迭代。

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

负值的原因是它正在环绕。如果你想找到最大的,你可以使用一个新的long变量来存储到目前为止最大值。另一种方法是简单地遍历范围反向

此外,您可以缩短循环,直到检查给定数字的平方根。如果找到一个因子,可以(num / ans)找到更大的因子。

答案 1 :(得分:0)

您可以通过一些技巧显着加快这一过程:

  1. 检查除两个以外的任何偶数都没有用。仅使用两个和奇数作为潜在因素。
  2. 当您找到素数因子时,请将输入数除以该值。这使得它随着你的进展而变得更小,显着缩短了时间。
  3. 当潜在因子大于输入数字的平方根时停止比当潜在因子大于数字的一半时停止要快得多。另外,不要计算条件内的平方根。将其保存在变量中,并仅在输入数字被其中一个主要因子除以后才会重新计算。
  4. 不要费心检查奇数潜在因素是否为素数。如果他们不是素数,那么他们自己的素因子已经被分开了数量,因此潜在因素将很快失败(x % factor == 0L)检查,这比isPrime(factor)检查要快得多。
  5. 以下代码结合了这些想法,并在大约十分之一秒内找到答案:

    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));
        }
    }
    

答案 2 :(得分:0)

一种可能的解决方案是使用递归,如下所示:

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);
        }
    }

}