Finding factors of a given integer
Asked Answered
H

14

12

I have something like this down:

int f = 120;
for(int ff = 1; ff <= f; ff++){
    while (f % ff != 0){            
}

Is there anything wrong with my loop to find factors? I'm really confused as to the workings of for and while statements, so chances are they are completely wrong.

After this, how would I go about assigning variables to said factors?

Horrified answered 27/12, 2011 at 16:49 Comment(5)
Yeah, there's something wrong - there's no code inside. How do you plan to find factors? Where do you expect to store them?Curator
Just a sidenote: i'd not use "f" and "ff", because it doesn't help readability at all.Blowup
Use better variable names, you probably don't want a while loop to check if a number divides into f evenly with no remainder (it's a single conditional check, so doesn't that sound like an if?). As for keeping factors, do you know anything about Java Collections?Foursome
en.wikipedia.org/wiki/Sieve_of_EratosthenesKuroshio
I suggest you step through your code in a debugger, this will make it clear what each line is doing and why. It will help you understand your program and perhaps make it obvious what you need to fix.Timisoara
O
17

The following code will return a list of all factors of a given number:

public ArrayList<Integer> findFactors(int num) {        
    ArrayList<Integer> factors = new ArrayList<Integer>();

    // Skip two if the number is odd
    int incrementer = num % 2 == 0 ? 1 : 2;

    for (int i = 1; i <= Math.sqrt(num); i += incrementer) {

        // If there is no remainder, then the number is a factor.
        if (num % i == 0) {
            factors.add(i);

            // Skip duplicates
            if (i != num / i) {
                factors.add(num / i);
            }

        }
    }

    // Sort the list of factors
    Collections.sort(factors);

    return factors;
}

This answer improves Sharad Dargan's answer in two ways:

  1. Based on an idea used in this answer, you can speed up the solution by determining the value to increment by, based on whether the number is even or odd.

    Add the following line of code before the for loop:

    int incrementer = num % 2 == 0 ? 1 : 2;
    

    Then change the last part of the loop to:

     i += incrementer
    

    If the number is odd, it then will skip all even numbers, rather than always incrementing by one no matter what.

  2. Sharad stores the upper limit value in a variable and then uses that variable in the for loop:

    int upperlimit = (int)(Math.sqrt(a));
    ...
    for(int i = 1; i <= upperlimit; i+= 1)
    

    Instead, place Math.sqrt(num) directly in the for loop and skip the upper limit variable:

    for (int i = 1; i <= Math.sqrt(num); i += incrementer) {
    

    This will allow you to skip the casting part of the code, creating cleaner code.


Some JUnit test cases you can then use:

@Test
public void test12() {
    FindFactors find = new FindFactors();

    int num = 12;
    List<Integer> factors = Arrays.asList(1, 2, 3, 4, 6, 12);

    assertEquals(factors, find.findFactors(num));
}

@Test
public void test1000000() {
    FindFactors find = new FindFactors();

    int num = 1000000;
    List<Integer> factors = Arrays.asList(1, 2, 4, 5, 8, 10, 16, 20, 25, 32, 40, 50, 64, 80, 100, 125, 160, 200,
            250, 320, 400, 500, 625, 800, 1000, 1250, 1600, 2000, 2500, 3125, 4000, 5000, 6250, 8000, 10000, 12500,
            15625, 20000, 25000, 31250, 40000, 50000, 62500, 100000, 125000, 200000, 250000, 500000, 1000000);

    assertEquals(factors, find.findFactors(num));
}

@Test
public void test1() {
    FindFactors find = new FindFactors();

    int num = 1;
    List<Integer> factors = Arrays.asList(1);

    assertEquals(factors, find.findFactors(num));
}

@Test
public void test0() {
    FindFactors find = new FindFactors();

    int num = 0;
    List<Integer> factors = new ArrayList<Integer>();

    assertEquals(factors, find.findFactors(num));
}
Obligate answered 21/8, 2017 at 3:55 Comment(1)
Putting the Math.sqrt directly inside makes it slower because int-double comparison is slow compared to int-int. Also, before the compiler kicks in, it has to keep evaluating Math.sqrt, which is really slow.Papacy
F
11

Here is how to get all factors of the given number.

public class Factors {

    public static void main(String[] args){
        int n = 420;

        for(int i=2; i<=n; i++){
            while(n%i==0){
                System.out.println(i + "| " + n);
                System.out.println(" -----");
                n = n/i;
            }
        }
    }
}

Output:

2| 420
 -----
2| 210
 -----
3| 105
 -----
5| 35
 -----
7| 7
 -----
Fanaticize answered 2/12, 2015 at 5:40 Comment(2)
I don't think thats all the factors.. This tweak seems to work: public static int getFactors(int n) { int last = 0; if (n<=1) { return 1; } for(int i=2; i<=n; i++){ if(n%i==0){ System.out.println(i + "| " + n); System.out.println(" -----"); last = i; } } if (last != 0) { return getFactors(n/last); } else { return 1; } }Ruffo
This gives all the prime-factors, not all the factors of a given number.Shorthand
A
11
public class Solution {
    public ArrayList<Integer> allFactors(int a) {

        int upperlimit = (int)(Math.sqrt(a));
        ArrayList<Integer> factors = new ArrayList<Integer>();
        for(int i=1;i <= upperlimit; i+= 1){
            if(a%i == 0){
                factors.add(i);
                if(i != a/i){
                    factors.add(a/i);
                }
            }
        }
        Collections.sort(factors);
        return factors;
    }
}

The above solution simply works like calculating prime factors. The difference being for every prime factor we keep calculating the other part of the product i.e the reqd number.

Antisthenes answered 22/2, 2016 at 18:6 Comment(1)
I've added another answer here that is a slightly faster and cleaner version of this solution. I included a detailed explanation of the differences in the answer.Obligate
C
3

In order to find the factors of a given number, you only need to check upto the square root of the given number.

For example, in order to find the factors of 6, you only need to check till 2.45 (√6). The factors of 6 will be 1 and 2, and their converse numbers, i.e. 3 and 6.

I have made a program that determines the factors of a given number and displays them. Here is the necessary code:

    Scanner input = new Scanner(System.in);

    System.out.print("Enter integer: ");
    long num = input.nextLong();

    for(long i = 1; i <= Math.sqrt(num); i++) {
        if(num % i == 0) {
            System.out.println(i);
            if(i != num/i) {
                System.out.println(num/i);
            }
        }
    }

You just need this program to find the factors of a given number. However, if you want to take it a step further and display the factors arranged in ascending order, then the necessary code is as follows:

    Scanner input = new Scanner(System.in);

    System.out.print("Enter integer: ");
    long num = input.nextLong();

    ArrayList<Long> list1 = new ArrayList<>(), list2 = new ArrayList<>();

    long currentTime = System.currentTimeMillis();

    for(long i = 1; i <= Math.sqrt(num); i++) {
        if(num % i == 0) {
            list1.add(i);
            if(i != num/i) {
                list2.add(num/i);
            }
        }
    }

    int n1 = list1.size() - 1;
    int n2 = list2.size() - 1;

    for(int i = 0; i <= n1; i++) {
        System.out.println(list1.get(i));
    }

    for(int i = n2; i >= 0; i--) {
        System.out.println(list2.get(i));
    }

What this does: This program stores the factors of the number upto the number's square root in one list (list1), and the converse of these numbers in another list (list2). It then prints the elements of both lists (as shown).

Concupiscence answered 10/3, 2017 at 3:58 Comment(1)
As an alternative to my method for arranging the factors in ascending order, you could use Collections.sort(listName) as shown in Sharad Dargan's post.Concupiscence
B
2

There's nothing wrong with your for loop, but a while loop is the wrong thing to be using here. The logic of your for loop is:

  • Set ff to 1.
  • Keep going while ff <= f.
  • After you've done everything in the for loop, add 1 to ff.

This looks like it is exactly as you want.

The while loop isn't right, though. It will continue to do whatever code you write there for as long as ff is a factor of f, so unless you change them in the while code, you'll get an infinite loop. However, changing that to an if statement will give you what you want.

Since you're checking for factors, you don't actually need to check all possibilities up to f - only up to the square root of f. Whenever you find that ff is a factor, output both ff and f/ff as factors, unless f is a sqare number.

Bobble answered 27/12, 2011 at 21:34 Comment(0)
P
1
public static void printFactors(int number) {
    if (number < 1 )
        System.out.println("Invalid Value");

    for (int i = 1 ; i <= number ; ++i) {
        if ( number % i == 0)
                System.out.println(i);
        }
    }
}
Pop answered 4/7, 2019 at 7:19 Comment(0)
B
0

It looks like you are not going to do something with either f or ff in your while loop? If so, the expression f%ff != 0 is either false (and then it will go to the next in the for loop), or it is true, and it will end up in an infinite loop.

Are you sure you need the while like this?

Blowup answered 27/12, 2011 at 16:52 Comment(0)
R
0

Slightly modified solution: You can first check if variable x is divisible by variable y. If yes, we will count 1 and will repeat this process. For the loop counter, x/y is used and you should check x>0 to avoid repetition when x becomes zero but loop is not finished yet.

   public class Factor {

    public static void main(String[] args) {

        int x = 48;
        int x1 = x;
        int y = 2;
        int k = x / y;
        int j = 0;
        for (int i = 1; i < k; i++) {
            if ((x % y) == 0 && x > 0)
                j++;
            x = x / 2;
        }
        System.out.println(+x1 + " is a factor of " + y + " for " + j
                + " times.");

    }
}
Rossiter answered 22/10, 2014 at 9:23 Comment(0)
M
0

I got all the factors just fine with this (I just modified the algorithm in the question).

int num1 = 120;

for(int num2=1;num2<=num1;num2++)
{
  if (num1%num2 != 0)
    System.out.println(num2);
}
Moffitt answered 9/10, 2015 at 0:44 Comment(0)
H
0
    import java.util.Scanner;
    public class Factors 
    {
        Scanner scn=new Scanner(System.in);
        int num=scn.nextInt();
        public void findFactor()
        {
           System.out.println("Factors are");
           System.out.println("1");
           for(int i=2;i<=num;i++)
           {
                if(num%i==0)
                {
                    num=num/i;
                    System.out.println(i);
                    i=2;
                }
           }
        }
public static void main(String[] args) 
{
    while(1==1)
    {
        System.out.println("Enter a Number");
        Factors fct=new Factors();
        fct.findFactor();
    }
}

}

Heath answered 3/7, 2018 at 3:8 Comment(2)
A code-only answer that is poorly formatted is liable to downvotes.Moonrise
comments explaining why your solution is cleaner or more accurate to the question are required to ensure your answer doesn't get downvotesHyden
R
0

Utilizing Streams introduced in Java 8, the following will print the factors for a given number.

int input = 1500;
IntStream.rangeClosed(1, input)
         .filter(e -> input % e == 0)
         .forEach(System.out::println);
Rora answered 3/8, 2018 at 20:32 Comment(0)
P
0

This is how you write it yourself like a boss. Needs to add if statements to handle one and two, but besides that; this method is as sexy as it gets

  public static void primerize(int n){
  boolean reduced = false;
  while(n > 2){
     if(n%2 == 0){
        System.out.println(2 + "," + n/2);
        n /= 2;
     }
     else{
        int i = isPrime(n); 
        if(i == n && reduced == false){
           System.out.println(1 + "," + n);
           n /= n;
        }
        else if(i == n){
           n/= n;
        }
        else{
           System.out.println(i + "," + n/i);
           n = i;
           reduced = true;
        }
     }
  }}



public static int isPrime(int n){
  for(int i = (n/3); i > 0; i--){
     if(i == 1){
        return n;
     }
     else if(n%i == 0){
        return i;
     }
  }
  return 0;}
Popinjay answered 11/10, 2018 at 12:55 Comment(0)
C
-1

This code will give you the factors.

ArrayList<Integer> arr = new ArrayList<>();
        int x=48;
        int y=1;
        while(x!=1)
        {
            if(x%y==0)
            {
                x=x/y;
                arr.add(y);
                if(y==1)
                {
                    y++;
                }
            }
            else
            {
                y+=1;
            }
        }
        System.out.println(arr);
Caution answered 30/10, 2014 at 21:29 Comment(0)
M
-5

Easiest way using recursive function

public static int factorial(int n){
        if(n!=1)
            return n*factorial(n-1);
        return 1; 
}   
Mieshamiett answered 30/4, 2016 at 14:46 Comment(1)
OP asked for factors, not factorial. Downvote for that.Mymya

© 2022 - 2024 — McMap. All rights reserved.