简体   繁体   中英

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?

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"? Also, if you notice, the run time for the program was a little over 5 hours. How do I speed up this process?

You are using an int for the for loop, which is overflowing. 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. 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.

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) .

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

}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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