【问题标题】:Finding factors of a given integer查找给定整数的因子
【发布时间】:2012-01-28 15:26:49
【问题描述】:

我有这样的事情:

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

我的循环查找因子有什么问题吗?我对 for 和 while 语句的工作原理感到非常困惑,所以它们很可能是完全错误的。

在此之后,我将如何将变量分配给所述因素?

【问题讨论】:

  • 是的,有问题 - 里面没有代码。你打算如何寻找因素?您希望将它们存放在哪里?
  • 只是一个旁注:我不会使用“f”和“ff”,因为它根本不利于可读性。
  • 使用更好的变量名,你可能不希望 while 循环检查一个数字是否均匀地分成 f 没有余数(这是一个单一的条件检查,所以不是听起来像if?)。至于保持因素,你知道Java Collections吗?
  • 我建议你在调试器中单步调试你的代码,这样可以清楚每一行在做什么以及为什么。它将帮助您了解您的程序,并可能让您清楚地了解您需要修复的内容。

标签: java for-loop integer while-loop factors


【解决方案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);
        }
    }
}

【讨论】:

    【解决方案2】:

    这就是你像老板一样自己写的方式。需要添加 if 语句来处理一和二,但除此之外;这个方法很性感

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

    【讨论】:

      【解决方案3】:

      以下代码将返回给定数字的所有因子的列表:

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

      这个答案从两个方面改进了Sharad Dargan's answer

      1. 基于this answer 中使用的一个想法,您可以通过根据数字是偶数还是奇数确定要递增的值来加快求解速度。

        在for循环前添加如下代码:

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

        然后将循环的最后一部分改为:

         i += incrementer
        

        如果数字是奇数,它将跳过所有偶数,而不是无论如何总是加一。

      2. Sharad 将上限值存储在一个变量中,然后在 for 循环中使用该变量:

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

        改为将Math.sqrt(num)直接放在for循环中,跳过上限变量:

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

        这将允许您跳过代码的强制转换部分,创建更简洁的代码。


      然后您可以使用一些 JUnit 测试用例:

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

      【讨论】:

      • 将 Math.sqrt 直接放在里面会使其变慢,因为与 int-int 相比,int-double 比较慢。此外,在编译器启动之前,它必须继续评估 Math.sqrt,这真的很慢。
      【解决方案4】:

      利用 Java 8 中引入的 Streams,以下将打印给定数字的因子。

      int input = 1500;
      IntStream.rangeClosed(1, input)
               .filter(e -> input % e == 0)
               .forEach(System.out::println);
      

      【讨论】:

        【解决方案5】:
            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();
            }
        }
        

        }

        【讨论】:

        • 格式错误的纯代码答案可能会被否决。
        • cmets 需要解释为什么您的解决方案对问题更清晰或更准确,以确保您的答案不会被否决
        【解决方案6】:

        为了找到给定数字的因数,您只需要检查给定数字的平方根即可。

        例如,为了找到 6 的因数,您只需要检查直到 2.45 (√6)。 6 的因数是 1 和 2,以及它们的倒数,即 3 和 6。

        我编写了一个程序来确定给定数字的因数并显示它们。这是必要的代码:

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

        你只需要这个程序来找到给定数字的因数。但是,如果你想更进一步,将因子升序排列显示出来,那么必要的代码如下:

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

        这是做什么的:这个程序将数字的因数存储到一个列表 (list1) 中,并将这些数字的倒数存储在另一个列表 (list2) 中。然后打印两个列表的元素(如图所示)。

        【讨论】:

        • 作为我按升序排列因素的方法的替代方法,您可以使用 Collections.sort(listName),如 Sharad Dargan 的帖子中所示。
        【解决方案7】:
        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;
            }
        }
        

        上面的解决方案就像计算素数一样简单。 不同之处在于我们不断计算产品的其他部分,即请求数。

        【讨论】:

        • 我添加了另一个答案here,它是该解决方案的一个稍微更快、更简洁的版本。我详细解释了答案中的差异。
        【解决方案8】:

        使用递归函数的最简单方法

        public static int factorial(int n){
                if(n!=1)
                    return n*factorial(n-1);
                return 1; 
        }   
        

        【讨论】:

        • OP 要求因子,而不是因子。对此投反对票。
        【解决方案9】:

        这里是如何获取给定数字的所有因子。

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

        输出:

        2| 420
         -----
        2| 210
         -----
        3| 105
         -----
        5| 35
         -----
        7| 7
         -----
        

        【讨论】:

        • 我不认为这就是所有因素。这个调整似乎有效:public static int getFactors(int n) { int last = 0; if (n&lt;=1) { return 1; } for(int i=2; i&lt;=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; } }
        • 这给出了所有素因子,而不是给定数字的所有因子。
        【解决方案10】:

        我得到了所有因素都很好(我只是修改了问题中的算法)。

        int num1 = 120;
        
        for(int num2=1;num2<=num1;num2++)
        {
          if (num1%num2 != 0)
            System.out.println(num2);
        }
        

        【讨论】:

          【解决方案11】:

          此代码将为您提供因素。

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

          【讨论】:

            【解决方案12】:

            稍微修改的解决方案:您可以先检查变量 x 是否可以被变量 y 整除。如果是,我们将计数 1 并重复此过程。对于循环计数器,使用 x/y,当 x 变为零但循环尚未完成时,应检查 x>0 以避免重复。

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

            【讨论】:

              【解决方案13】:

              您的for 循环没有任何问题,但在这里使用while 循环是错误的。 for 循环的逻辑是:

              • ff 设置为1。
              • ff &lt;= f 继续前进。
              • for 循环中完成所有操作后,将 1 添加到 ff

              这看起来正是你想要的。

              不过,while 循环是不正确的。只要fff 的一个因子,它将继续执行您在那里编写的任何代码,因此除非您在while 代码中更改它们,否则您将获得无限循环。但是,将其更改为 if 语句将满足您的需求。

              由于您正在检查因子,因此您实际上不需要检查直到 f 的所有可能性 - 只需要检查 f 的平方根。每当您发现ff 是一个因数时,将fff/ff 作为因数输出,除非f 是一个平方数。

              【讨论】:

                【解决方案14】:

                看起来您不会在 while 循环中使用 fff 做某事?如果是这样,则表达式f%ff != 0 要么为假(然后将转到 for 循环中的下一个),要么为真,并以无限循环结束。

                你确定你需要这样的时间吗?

                【讨论】:

                  猜你喜欢
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 2023-04-09
                  相关资源
                  最近更新 更多