繁体   English   中英

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

[英]Project Euler Number 3: Largest prime factor

这是我的代码:

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)

如何打印出最大的数字? 当“ x”应该不断增加而不是减少时,为什么输出显示负数?

更新

这是我编辑的代码:

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)

如何获得最终答案以“ 6857”而不是“ 0”的形式打印出来? 另外,如果您注意到,该程序的运行时间将超过5个小时。 如何加快此过程?

您正在for循环中使用int ,该循环正在溢出。 使用长变量进行迭代。

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

负值的原因是它回绕。 如果您只想找到最大的,则可以使用新的long变量来存储到目前为止的最大可见数。 另一种方法是简单地反向迭代范围。

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

您可以通过以下一些技巧大大加快该过程:

  1. 检查两个以外的偶数没有用。 仅使用两个和奇数作为潜在因子。
  2. 找到素数时,将输入数除以该数。 这样一来,它的体积就会大大减小,从而大大节省了时间。
  3. 当潜在因子大于输入数的平方根时停止比在潜在因子大于输入数的平方根时停止快得多。 另外,不要计算条件内部的平方根。 将其保存在变量中,然后仅当输入数字除以其主要因子之一而已更改时,才重新计算它。
  4. 不要费心检查奇数潜在因素是否为素数。 如果它们不是素数,则它们自己的素因数将已经从数量中除掉,因此潜在因数将很快无法通过(x % factor == 0L)检查,这比isPrime(factor)

以下代码结合了这些想法,并在大约十分之一秒的时间内找到了答案:

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

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

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