Find the largest prime factor of a given number - java

I am writing this method which should return the largest prime factor of a given number. It was working fine till 45 was entered and the output was 15, even though the output should be 5. I am struggling to find the bug. Please help.
public static int getLargestPrime(int number) {
if (number < 0) {
return -1;
}
for (int i = number-1; i > 1; i--) {
if (number % i == 0) {
for (int j = 2; j < i; j++) {
if (i % j == 0) {
continue;
}
return i;
}
}
}
return -1;
}

You need to add a flag to check the divisibility of the value i. It will remain true only if i is a prime number. Later if the flag remains true, you can return i else you need to continue iterating
What's happening in your code is that when i=15, and the inner loop starts iterating starting from 2, 15%2!=0 so it skips the if condition and returns 15
for (int i = number-1; i > 1; i--) {
if (number % i == 0) {
bool flag = true;
for (int j = 2; j < i; j++) {
if (i % j == 0) {
flag = false;
break;
}
}
if(flag)
return i;
}
}

In short: The "prime" validation is wrong.
In your code, in the inner loop, you expect all numbers will be factors of "i", which is of course wrong.
Your code will retrieve the largest factor of your input, which there is a number which is not a factor of it (i % j != 0), therefore the largest factor of it (regardless of primality).

Find the prime numbers before the input number
Sort the prime numbers in reverse order
Iterate over the prime numbers and check whether its an exact multiple
If its an exact multiple return the prime number
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
class PrimeFactorTest {
public static void main(String[] args) throws Exception {
int[] inputs = new int[]{-100, -25, -2, -1, 0, 1, 2, 3, 4, 5, 100, 1223, 2000, 874032849,
Integer.MAX_VALUE, Integer.MAX_VALUE};
for (final int input : inputs) {
Optional primeFactor = largestPrimeFactor(input);
if (primeFactor.isPresent()) {
System.out.println("Largest Prime Factor of " + input + " is " + primeFactor.get());
} else {
System.out.println("No Prime Factor for " + input);
}
}
}
public static Optional<Integer> largestPrimeFactor(final int input) {
if (input < 0) {
return largestPrimeFactor(Math.abs(input));
}
final int sqrt = (int) Math.sqrt(input);
List<Integer> primes = getPrimesInDescendingOrder(sqrt);
if (primes.size() == 0) {
return Optional.empty();
}
for (final int prime : primes) {
if (input % prime == 0) {
return Optional.of(prime);
}
}
return Optional.of(input);
}
private static List<Integer> getPrimesInDescendingOrder(final int input) {
if (input < 2) {
return new ArrayList<>();
}
List<Integer> primes = new ArrayList<>();
primes.add(2);
for (int current = 3; current <= input; current++) {
boolean isPrime = true;
for (int prime : primes) {
if (current % prime == 0) {
isPrime = false;
}
}
if (isPrime) {
primes.add(current);
}
}
primes.sort(Collections.reverseOrder());
return Collections.unmodifiableList(primes);
}
}

I came up with this. If you start at 2 and work up the way, you are eliminating all the non-primes before you hit them, as they will no-longer be factors of the remainder.
import static org.junit.Assert.assertEquals;
import org.junit.Test;
public class LargestPrimeFactor {
#Test
public void testGetLargestPrime() {
assertEquals(2, getLargestPrime(2));
assertEquals(3, getLargestPrime(3));
assertEquals(2, getLargestPrime(4));
assertEquals(5, getLargestPrime(5));
assertEquals(3, getLargestPrime(6));
assertEquals(7, getLargestPrime(7));
assertEquals(2, getLargestPrime(8));
assertEquals(3, getLargestPrime(9));
assertEquals(23, getLargestPrime(23*23*7*2*5*11*11));
}
int getLargestPrime(int number) {
for (int i = 2; number > i; i++) {
while (number > i && number % i == 0) {
number = number / i;
}
}
return number;
}
}

It wasn't working fine until it reached 45. It failed for 4, 8, 12, 16, 18, 20, 24, 27, 28, 30, 32, 36, 40, 42, and 44. It returned -1 for every prime number, which is correct, but it also returned -1 for 4. It usually finds the largest factor, regardless of whether it's prime.
Your outer loop finds factors, starting with the largest. Your inner loop doesn't make sense. It needs to have a test for primality. It looks like you meant it to quit when it finds a factor of i, but it doesn't do that. Instead, it quits when it finds a number that isn't a factor. The continue statement tells it to go to the next value of j. You probably meant for it to go on to the next value of i. To do that, you could use break. That would bail out of the inner loop. Or you could label the outer loop and use the label in the continue statement, which is probably what you had in mind:
candidates:
for (int i = number - 1; i > 1; i--) {
if (number % i == 0) {
for (int j = 2; j < i; j++) {
if (i % j == 0) {
continue candidates; // This continues the outer loop
}
return i;
}
}
}
return -1;
That gets you closer, but it still fails for powers of two, and for cases where it finds p^n where p is a prime number.
Also, there's no point in starting the outer loop with number-1. You can skip all the numbers higher than number/2. None of them will produce a modulo of zero.

I would recommend doing something like this. First, consider 2*2*3*47 = 564. The square root of 564 is <= 24. So all you need to do is divide by numbers up to 24. First, eliminate 2. That leaves 3*47. Next is 3 which leaves 47. Since no other number from 4 thru 24 divides 47, 47 must be a prime. If it were composite, it's prime factors would have been factored out by one of the earlier divisors.
This can be further optimized by factoring out 2 in a separate loop. Then starting with 3, start dividing by only the odd numbers (2 already eliminated the even factors if there were any).
If the situation arises when the number is reduced to 1, then the last divisor that did the reduction must be the largest prime.
int[] testData = { 2, 10, 2 * 2 * 5, 2 * 3 * 47 * 5,
2 * 2 * 2 * 3 * 3 * 3 * 17 * 17 * 17 };
for (int v : testData) {
System.out.printf("%8s - largest prime factor = %s%n", v,
getLargestPrime(v));
}
Prints
2 - largest prime factor = 2
10 - largest prime factor = 5
20 - largest prime factor = 5
1410 - largest prime factor = 47
1061208 - largest prime factor = 17
The method
public static int getLargestPrime(int number) {
// no primes less than 2 exist.
if (number < 2) {
return -1;
}
while (number % 2 == 0) {
number /= 2;
}
int lastDivisor = 2;
for (int d = 3; d <= Math.sqrt(number); d += 2) {
lastDivisor = d;
while (number % d == 0) {
number /= d;
}
}
return number == 1 ? lastDivisor : number;
}

This code will help you find the largest prime number. Most online servers won't allow it to run. Just change the value of n.
public class PrimeExample{
public static void main(String args[]){
for(int n = 100;n<=1000;n++){
int i,m=0,flag=0;
m=n/2;
if(n==0||n==1){
System.out.println(n+" is not prime number");
}else{
for(i=2;i<=m;i++){
if(n%i==0){
System.out.println(n+" is not prime number");
flag=1;
break;
}
}
if(flag==0) { System.out.println(n+" is prime number"); }
}//end of else
}
}
}

Related

Highly divisible triangular number

Highly divisible triangular number, my solution
My solution of challenge from Project Euler takes too much time to execute. Although on lower numbers it works fine. Anyone could look up to my code and give me any advice to improve it?
The content of the task is:
The sequence of triangle numbers is generated by adding the natural numbers. So the 7th triangle number would be 1 + 2 + 3 + 4 + 5 + 6 + 7 = 28. The first ten terms would be:
1, 3, 6, 10, 15, 21, 28, 36, 45, 55, ...
Let us list the factors of the first seven triangle numbers:
(1: 1),
(3: 1,3),
(6: 1,2,3,6),
(10: 1,2,5,10),
(15: 1,3,5,15),
(21: 1,3,7,21),
(28: 1,2,4,7,14,28).
We can see that 28 is the first triangle number to have over five divisors.
What is the value of the first triangle number to have over five hundred divisors?
`public static void main(String[] args) {
int sum = 0;
int count = 0;
for (int i = 1; i <= Integer.MAX_VALUE; i++) {
sum += i;
for (int j = 1; j <= sum; j++) {
if (sum % j == 0) {
count++;
}
}
if (count > 500) {
System.out.println(sum);
break;
} else {
count = 0;
}
}
}`
Consider any set of primes (p1, p2, p3. . . pn) that factor a given number. Then the total number of divisors of that number are the products of (e1 + 1, e2 + 1, e3 + 1 ... en+1) where e is the exponent of the corresponding prime factor (i.e. the number of times that prime divides some number N).
There are three pieces to this answer.
The main driver code
the method to find the prime divisors.
and a Primes class that generates successive primes using an iterator.
The Driver
first instantiate the Primes class and initialize the triangleNo
Then continually generate the next triangular number until the returned divisor count meets the requirements.
Primes primes = new Primes();
long triangleNo = 0;
for (long i = 1;; i++) {
triangleNo += i;
int divisors = getDivisorCount(triangleNo, primes);
if (divisors > 500) {
System.out.println("No = " + triangleNo);
System.out.println("Divisors = " + divisors);
System.out.println("Nth Triangle = " + i);
break;
}
}
prints
No = 76576500
Divisors = 576
Nth Triangle = 12375 NOTE: this is the value n in n(n+1)/2.
Finding the prime factors
takes a value to factor and an instance of the Primes class
continues to test each prime for division, counting the number of times the remainder is 0.
a running product totalDivisors is computed.
the loop continues until t is reduced to 1 or the current prime exceeds the square root of the original value.
public static int getDivisorCount(long t, Primes primes) {
primes.reset();
Iterator<Integer> iter = primes;
int totalDivisors = 1;
long sqrtT = (long)Math.sqrt(t);
while (t > 1 && iter.hasNext()) {
int count = 0;
int prime = iter.next();
while (t % prime == 0) {
count++;
t /= prime;
}
totalDivisors *= (count + 1);
if (prime > sqrtT) {
break;
}
}
return totalDivisors;
}
The Primes class
A class to generate primes with a resettable iterator (to preserve computed primes from previous runs the index of an internal list is set to 0.)
an iterator was chosen to avoid generating primes which may not be required to obtain the desired result.
A value to limit the largest prime may be specified or it may run to the default.
Each value is tested by dividing by the previously computed primes.
And either added to the current list or ignored as appropriate.
if more primes are needed, hashNext invoked a generating to increase the number and returns true or false based on the limit.
class Primes implements Iterator<Integer> {
private int lastPrime = 5;
private List<Integer> primes =
new ArrayList<>(List.of(2, 3, 5));
private int index = 0;
private int max = Integer.MAX_VALUE;
public Primes() {
}
public Primes(int max) {
this.max = max;
}
#Override
public boolean hasNext() {
if (index >= primes.size()) {
generate(15); // add some more
}
return primes.get(index) < max;
}
#Override
public Integer next() {
return primes.get(index++);
}
private void generate(int n) {
outer: for (int candidate = lastPrime + 2;;
candidate += 2) {
for (int p : primes) {
if (p < Math.sqrt(candidate)) {
if (candidate % p == 0) {
continue outer;
}
}
}
primes.add(candidate);
lastPrime = candidate;
if (n-- == 0) {
return;
}
}
}
public void reset() {
index = 0;
}
}
Note: It is very likely that this answer can be improved, by employing numerical shortcuts using concepts in the area of number theory or perhaps even basic algebra.

Calculate amicable numbers efficiently to a very high upper limit in java

I have a program that computes amicable pairs of numbers up to a certain limit and prints them out to Stdout. FYI - two numbers are amicable if each is equal to the sum of the proper divisors of the other (for example, 220 and 284).
My program works fine for the first 8 or so pairs, but the problem is when the limit gets to a very high number e.g 5 million it becomes very slow. Is there a way to optimize this so that it computes much faster?
Here is my code
public class Amicable{
private static int num1, num2, limit = 5000000;
public static void main(String[] args){
for(int i = 1; i < limit;i++){
num1= sumOfDivisors(i);
num2 = sumOfDivisors(i)
if(num1 == num2){
System.out.println(num2 + " " + num1);
}
}
}
}
private static int sumOfDivisors(int n){
int sum = 0;
for(int i=1;i<=n/2;i++){
if(n%i==0){
sum =sum+i;
}
}
return sum;
}
}
You should make the innermost loop efficient.
static int sumOfDivisors(int n) {
int sum = 1;
int max = (int) Math.sqrt(n);
if (n > 1 && max * max == n) // in case of n is perfect square number
sum -= max;
for (int i = 2; i <= max; ++i)
if (n % i == 0)
sum += i + n / i;
return sum;
}
If n = 220, it is divisible by 2, so you can add 2 and 110 to the sum at the same time. However, if n is a perfect square number, for example n = 100, it is divisible by 10, but if 10 and 10 are added, they will duplicate, so subtract it in advance.
output for limit =2000000:
220 284
1184 1210
2620 2924
5020 5564
6232 6368
10744 10856
12285 14595
17296 18416
63020 76084
66928 66992
.....
1468324 1749212
1511930 1598470
1669910 2062570
1798875 1870245
It took 7 seconds on my PC.
You could change the statement of "if(i<num1)" to "if(i<num1 || num1<limit)".
This is a more efficient and faster approach.
Inside sumOfDivisors:
Start iteration from 2. (no a big deal) and add 1 during return time with sum as 1 is also a divisor.
Modify loop termination logic, i <= Math.sqrt(n).
For any number ‘num’ all its divisors are always less than and equal to ‘num/2’ and all prime factors are always less than and equal to sqrt(num).
If n%i == 0, then check, both divisors are are equal or not. If equal, take one if not equal then take both one.
private static int sumOfDivisors(int n) {
int sum = 0;
int sqrt = Math.sqrt(n);
for (int i = 2; i <= sqrt; i++) {
if (n % i == 0) {
if(i == (n/i))
sum = sum + i;
else
sum += (i+ n/i);
}
}
return sum+1;
}

Trying to find the smallest positive number that is evenly divisible by all of the numbers from 1 to 20

I'm trying to find the smallest positive number that is evenly divisible by all of the numbers from 1 to 20. We are given that 2520 is the smallest number that can be divided by each of the numbers from 1 to 10 without any remainder. My find() finds the number starting from 2520 that is divisible by all numbers from 1-20 but is returning 2520 for some reason. I cannot find what's wrong about my find()?
public class Solution {
public ArrayList<Integer> list = new ArrayList<Integer>();
// creating a list of integers from 1 to 20
public ArrayList<Integer> addtolist() {
for (int i = 1; i <= 20; i++) {
list.add(i);
}
return list;
}
// finds the smallest positive number that is evenly divisible by all
of the numbers from 1 to 20
public int find() {
int num = 2520;
while(true) {
for(int i: list) {
if(num % i == 0) {
return num;
}
else {
num = num + 1;
}
}
}
}
public static void main(String[] args) {
Solution sol = new Solution();
sol.addtolist();
System.out.println(sol.find());//2520
}
}
Your find function returns num if any i in list divides it. It should only return num if every i in num is a divisor.
Although it has to be said that this is far from the most efficient solution to the problem.
You return from the for loop when (num % i == 0), given that i starts at 1 this always true. Instead you need to wait until the end to return:
public int find() {
int num = 2520;
while(true) {
boolean allDivisible = true;
for(int i: list) {
if(num % i != 0) {
allDivisible = false;
break;
}
}
if (allDivisible) {
return num;
else {
num = num + 1;
}
}
}
In your code:
for(int i: list) {
if(num % i == 0) {
return num; // Returns immediately.
}
else {
num = num + 1;
}
}
you return as soon as you find some number in the list that has a match. What you want to do is only return when you have found a value that matches all in the list.
Nice question!
long answer = LongStream.iterate(1, n -> n + 1)
.filter(n -> IntStream.rangeClosed(1, 20).allMatch(f -> n % f == 0))
.findFirst().getAsLong();
Answer is 232792560
There are obviously plenty of shortcuts using math (e.g. only looking at even numbers, ignoring numbers in 1 to 20 that are factors of other numbers in that range).

In Java how to find random factors of a given number

I have a given number. How can I find the factors of that number (for example, 5 and 3 for the number 15)? Here is the code I tried:
int factor1 = 2;
while ((a % factor1 != 0) && (a >= factor1)) {
d++;
}
if (factor1 == a){
d = 1;
}
But this gives me only the smallest factor (i.e a=3 all the time). I would like to get a random set of factors.
Loop through each number from 1 to N inclusively using the modulus operator (%). If n%currentNumber==0, they are a factor. Below, I did this using a for loop, outputting each factor as it is found.
int number=15;
for(int i = 1; i <= number; i++){
if(number%i==0){
System.out.println("Found factor: " + i);
}
}
As Theo said in a comment on this post, you can also use number/2, and arbitrarily include 1 and number.
int number=2229348;
System.out.println("Found factor: " + 1);
for(int i = 2; i <= number/2; i++){
if(number%i==0){
System.out.println("Found factor: " + i);
}
}
System.out.println("Found factor: " + number);
You can iterate through the numbers from 2 to a/2 and check if the given number divides a, which is done using the % operator:
int a = 15;
System.out.print("Divisors of " + a + ": ");
for(int i = 2; i <= a/2; ++i) {
if(a % i == 0) {
System.out.print(i + " ");
}
}
System.out.println();
This code prints all of the divisors of a. Not that you most probably want to ignore 1, since it divides all integers. Moreover, you don't need to check the numbers until a, because no number bigger than a / 2 can actually divide a apart from a itself.
The while loop with default values of a=15 and multiple=2 is already in an infinite loop. You need to correct that and check for subsequent increments of multiple whenever a%multiple ! = 0
public class Factors {
public static void main(String[] args){
/**
int multiple1=2,d=0,a=15; //multiple to be rephrased as factor
while((a%multiple1 != 0)&&(a>=multiple1)){
multiple1++; //this will increment the factor and check till the number itself
//System.out.println(multiple1+" is not a factor of a");
}
if(multiple1==a){
d=1;
}
*commented the original code
*/
int factor=1,d=0,a=20; //multiple rephrased as factor
while(a/2>=factor){ //re-arranged your while condition
factor++;
if((a%factor==0))
d++; //increment factor count whenever a factor is found
}
System.out.println("Total number of factors of a : "+(d+2)); // 1 and 'a' are by default factors of number 'a'
}
}
To find all factors inlcuding 1 and the number itself you can do something like below:
//Iterate from 2 until n/2 (inclusive) and divide n by each number.
//Return numbers that are factors (i.e. remainder = 0). Add the number itself in the end.
int[] findAllFactors(int number) {
int[] factors = IntStream.range(1, 1 + number / 2).filter(factor -> number % factor == 0).toArray();
int[] allFactors = new int[factors.length+1];
System.arraycopy(factors,0,allFactors,0,factors.length);
allFactors[factors.length] = number;
return allFactors;
}
To find only prime factors you can do something like this:
//Iterate from 2 until n/2 (inclusive) and divide n by each number.
// Return numbers that are factors (i.e. remainder = 0) and are prime
int[] findPrimeFactors(int number) {
return IntStream.range(2, 1 + number/ 2).filter(factor -> number % factor == 0 && isPrime(factor)).toArray();
}
Helper method for primality check:
//Iterate from 2 until n/2 (inclusive) and divide n by each number. Return false if at least one divisor is found
boolean isPrime(int n) {
if (n <= 1) throw new RuntimeException("Invalid input");
return !IntStream.range(2, 1+n/2).filter(x -> ((n % x == 0) && (x != n))).findFirst().isPresent();
}
If you are not on Java 8 and/or not using Lambda expressions, a simple iterative loop can be as below:
//Find all factors of a number
public Set<Integer> findFactors(int number) {
Set<Integer> factors = new TreeSet<>();
int i = 1;
factors.add(i);
while (i++ < 1 + number / 2) {
if ((number % i) == 0) {
factors.add(i);
}
}
factors.add(number);
return factors;
}
public class Abc{
public static void main(String...args){
if(args.length<2){
System.out.println("Usage : java Abc 22 3");
System.exit(1);
}
int no1=Integer.parseInt(args[0]);
int no=Integer.parseInt(args[1]),temp=0,i;
for(i=no;i<=no1;i+=no){
temp++;
}
System.out.println("Multiple of "+no+" to get "+no1+" is :--> "+temp);
//System.out.println(i+"--"+no1+"---"+no);
System.out.println("Reminder is "+(no1-i+no));
}
}

program logic of printing the prime numbers

Can any body help to understand this java program?
It just prints prime numbers, as you enter how many you want and it works well.
class PrimeNumbers
{
public static void main(String args[])
{
int n, status = 1, num = 3;
Scanner in = new Scanner(System.in);
System.out.println("Enter the number of prime numbers you want");
n = in.nextInt();
if (n >= 1)
{
System.out.println("First "+n+" prime numbers are :-");
System.out.println(2);
}
for ( int count = 2 ; count <=n ; )
{
for ( int j = 2 ; j <= Math.sqrt(num) ; j++ )
{
if ( num%j == 0 )
{
status = 0;
break;
}
}
if ( status != 0 )
{
System.out.println(num);
count++;
}
status = 1;
num++;
}
}
}
I don't understand this for loop condition
for ( int j = 2 ; j <= Math.sqrt(num) ; j++ )
why we are taking sqrt of num...which is 3....why we assumed it as 3?
Imagine that n can be divided by a number k that is greater than sqrt(n). Then you have:
n = k * j
where j is a number which must be less than sqrt(n) (if both k and j are greater than sqrt(n) then their product would be greater than n).
So you only need to find the divisors that are less than or equals to sqrt(n) and you can find those that are greater than or equals to sqrt(n) by a simple division. In my example, once you have found j, you can find k = n / j.
The line in question is basically trying to find numbers that are factors of your given number (and eliminating them as not-primes). If you find no factors of a given number then you can say that the number is prime.
As far as finding factors goes, you only need to go up to sqrt(N) because if you go any higher you are looking at numbers you have already seen before. This is because every time you find a factor you actually find two factors. If a is a factor of N then N/a and a are both factors of N.
A number N is prime if the only integers that satisfy N = A*B are 1 and N (or N and 1).
Now to check a number N as prime we could search all A from 2 to N and B from 2 to N, to see if N=A*B. That would take O(N^2) time, and is really inefficient.
It turns out that we only need to divide N by a number and see if there is a remainder. This brings it down to O(N).
And further, we don't need to check all the way from A=2 to A=N. If A is greater than sqrt(N), then B must be less than sqrt(N). Therefore we only need to check A from 2 to sqrt(N) to see if N/A has a remainder.
If I'm right there is a theory in math, saying that nearly all prime numbers can be determined when checking numbers from 2 to square root of n instead of checking all numbers from 2 to n oder 2 to n/2.
The factor of a number can lie only from 1 to sqrt of num. So instead of checking from 1 till num for its factors, we check for all numbers from 1 to sqrt(num) so see if any of them divides num. If any divides num, it is not prime, else it is. This improves efficiency of code.
A quick but dirty solution..
import java.util.Scanner;
class testing
{
public static void main(String args[])
{
Scanner input = new Scanner(System.in);
int n, i, j, count = 1;
System.out.print("How many Numbers ? : ");
n = input.nextInt();
for(j = 1;count<=n;j++)
{
if(j==1 || j==2)
{
System.out.println(j);
count++;
continue;
}
for(i=2;i<=j/2;i++)
{
if(j%i==0)
break;
else if(i == j/2 && j%i != 0)
{
System.out.println(j);
count++;
}
}
}
}
}
public class PrimeNumber {
public static void main(String[] args) {
// TODO Auto-generated method stub
ArrayList a = new ArrayList();
for (int i = 1; i <= 100; ++i) {
if (isPrime(i))
a.add(i);
}
System.out.println("List : " + a);
}
public static boolean isPrime(int value) {
if (value <= 1)
return false;
if ((value % 2) == 0)
return (value == 2);
for (int i = 3; i <= value - 1; i++) {
if (value % i == 0) {
return false;
}
}
return true;
}
}

Categories