10

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?

Tot Zam
  • 7,081
  • 9
  • 45
  • 66
Wilson
  • 7,890
  • 19
  • 59
  • 98
  • 2
    Yeah, there's something wrong - there's no code inside. How do you plan to find factors? Where do you expect to store them? – duffymo Dec 27 '11 at 16:51
  • 6
    Just a sidenote: i'd not use "f" and "ff", because it doesn't help readability at all. – Nanne Dec 27 '11 at 16:51
  • 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? – wkl Dec 27 '11 at 16:52
  • 2
    http://en.wikipedia.org/wiki/Sieve_of_Eratosthenes – Romain Hippeau Dec 27 '11 at 17:01
  • 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. – Peter Lawrey Dec 28 '11 at 12:04

14 Answers14

15

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));
}
Neil
  • 756
  • 1
  • 10
  • 26
Tot Zam
  • 7,081
  • 9
  • 45
  • 66
  • 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. – Will Kanga May 06 '21 at 15:14
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
 -----
zdesam
  • 2,720
  • 3
  • 22
  • 30
  • 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; } }``` – GL2014 Feb 26 '17 at 21:16
  • 1
    This gives all the prime-factors, not all the factors of a given number. – Liadco Jan 04 '18 at 20:35
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.

Tilak Maddy
  • 3,027
  • 2
  • 26
  • 44
Sharad Dargan
  • 136
  • 1
  • 4
  • 1
    I've added another answer [here](https://stackoverflow.com/a/45789083/4660897) that is a slightly faster and cleaner version of this solution. I included a detailed explanation of the differences in the answer. – Tot Zam Aug 21 '17 at 03:56
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).

  • 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. – Jainil Ajmera Mar 10 '17 at 04:06
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.

DenverCoder8
  • 401
  • 6
  • 15
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);
        }
    }
}
Pavel Smirnov
  • 4,293
  • 3
  • 14
  • 23
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.");

    }
}
Tarek
  • 741
  • 6
  • 18
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);
}
Bry N.
  • 1
  • 1
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();
    }
}

}

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);
Michael B
  • 39
  • 1
  • 3
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;}
jacobr
  • 53
  • 5
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?

Nanne
  • 61,952
  • 16
  • 112
  • 157
-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);
Junaid Shirwani
  • 250
  • 1
  • 5
  • 19
-4

Easiest way using recursive function

public static int factorial(int n){
        if(n!=1)
            return n*factorial(n-1);
        return 1; 
}   
Jojo
  • 2,524
  • 1
  • 14
  • 21