I have started learning to code in Java and decided I would use the Project Euler site to give me little tasks to try and complete with each bit of new coding I learn. So I came
Thank you for all your help, after reading through the comments and answers I managed to condense the code much further to the following:
public class Largest_Prime_Factor_NEW_SOLUTION_2 {
static long Tn = 600851475143L;
public static void main(String[] args) {
for (long i = 2; i < Math.sqrt(Tn); i++) {
if(Tn % i == 0) {
Tn = Tn / i;
i--;
}
}
System.out.println(Tn);
}
}
and it works perfect! Thanks again for your help and time to help me understand. I understand it was more a mathematical problem than a coding problem, but it helped me understand a few things. I'm now off to learn something else :)
Since you are doing this as a learning exercise, when you have improved you current program enough, why not try solving the same problem in a different way? The Fermat Factorization Method finds large factors first.
This is java version of this:
static boolean isPrime(int n){
if (n == 2) return true;
if (n == 3) return true;
if (n % 2 == 0) return false;
if (n % 3 == 0) return false;
int i = 5;
int w = 2;
while (i * i <= n) {
if(n % i == 0)
return false;
i += w;
w = 6 - w;
}
return true;
}
As it is described by @Alexandru: It's a variant of the classic O(sqrt(N)) algorithm. It uses the fact that a prime (except 2 and 3) is of form 6k-1 and 6k+1 and looks only at divisors of this form.
A simple algorithm for factoring a composite number by trial division goes like this:
function factors(n)
f, fs := 2, []
while f * f <= n
while n % f == 0
fs.append(f)
n := n / f
f := f + 1
if n > 1
fs.append(n)
return fs
That algorithm can be improved, and there are better algorithms for factoring large numbers, but it's sufficient for your task. When you are ready for more, I modestly recommend the essay Programming with Prime Numbers at my blog, which includes implementations of that algorithm and others in Java.
What you can do is find the lowest divisor of Tn
. Suppose that is p
, find the lowest divisor again for Tn/p
and so on.
Now, at every step p
is prime[explanation below]. So collect them and they are the prime divisors of Tn
.
For better time-complexity, you can check for divisors up to upto ceil(sqrt(Tn))
only, instead of Tn-1
.
And when you start checking for prime divisor for Tn
, you can start with 2
. And once you get a prime divisor p
don't start again from 2
for Tn/p
. Because, Tn/p
is also a divisor of Tn
and since Tn
does not have divisors less than p
, Tn/p
does not have it too. So start with p
again[p
can have multiple power in Tn
]. If p
does not divide Tn
, move to p+1
.
Example :
Tn = 45
1. start with 2. 2 does not divides 45.
2. next test is for 3. 45 is divisible by 3. So 3 is a prime divisor of it.
3. Now check prime divisors from 45/3 = 15, but start with 3. not from 2 again.
4. Well, 15 is divisible by 3. So start with 15/3 = 5
5. Note for 5, ceil(sqrt(5)) is 3. But 5 is not divisible by 3. But since 4 > ceil(sqrt(5))
and we can say 5 is a prime without any doubt.
So the prime divisor of 45 are 3 and 5.
Why smallest divisor(except 1) of a number is a prime ?
Suppose above statement is false. Then a number N has a smallest yet composite divisor, say C.
So C|N
Now C is composite so, it has divisor less than itself but greater than one.
Say such a divisor of C is P.
So P|C , but we have C|N => P|N where 1 < P < C.
This contradicts our assumption that C is the smallest divisor of N, so smallest divisors of a number is always a prime.
There are many ways to improve a program like this, but the improvements have to do mostly with mathematics and not programming:
When looking for factors, check each number, not just primes. If you find a factor check if it's prime. You'll save yourself of many primality checks this way.
The greatest prime factor of a composite number can be at most the number's square root, so you can stop the iteration earlier.
Use a fast primality test instead of doing trial divisions http://en.wikipedia.org/wiki/Primality_test
Then again, this is a one-off. Don't overcomplicate it.